协程设计原理与汇编实现

协程:

1.为什么会有协程,解决什么问题?

2.原语

3.协程的切换

4.协程结构体定义

5.调度的策略

6.调度器如何定义

7.协程api的实现,hook

8.多核模式

9.如何测试

 

同步的编程方式,异步的性能

如果检测io与读写io在一个流程里面就是同步,如果不在一个流程里面就是异步

//同步
func (){

  while(1){

    epoll_wait();

    for(;;){

      recv();
      send();
    }
  }

}

 

 

 

//伪代码,异步

thread_cb(void *arg){
    recv();
    send();
}
func () {
    while(1) {
         epoll_wait();
         for(;;) {
              push_other_thread(); 
        }
    }
}

避免不了一个问题:同一个fd会在不同的线程中操作,解决是在recv前在封装一个poll,检测是否真的可读

 

协程是在send之后,将fd加入到epoll,然后让出到epoll_wait,这时有两个可能1、epoll_wait没有就绪的,在恢复到send。2、如果有就绪的,处理fd,recv。

协程运行流程:遇到io(send,recv等),resume,操作完后,再yield

goto只能在函数内部跳转。栈内跳转

 

有三种跳转方式:

1、setjmp/longjmp

2、ucontext

3、汇编

线程切换:先保存当前寄存器的值(save),然后切换到下一个线程(load),相当于保留现场和恢复现场

协程也一样,yield和resume   

一个fd对应一个协程作为网络io合适,做页面刷新,文件就不合适

 

问题:协程的状态应该用什么样的数据结构,新建,等待,就绪,睡眠

新建,就绪用队列

等待睡眠用红黑树,为什么不用小顶堆,因为小顶堆一次只能取一个

 

struct coroutine{

  struct cpu_register_set *set; //cpu

       void *func; //coroutine_entry;

       void *arg;

       void *retval;  //返回值

       void *stack_addr;  //栈,协程独立栈

      size_t stack_size; //栈的大小

  queue(struct coroutine) *ready;

  retree(struct coroutine) *wait;

  rebree(struct coroutine) *sleep;//optional

}

所有的协程再就绪队列中都存在,调度的时候首先先判断sleep,然后判断wait,最后判断就绪。因此这几种状态中会有重复的。

 

hook,可以将系统的函数重定向为自己写的函数,

 

mysql -->开发接口

1.增删改查

2.存储过程

3.二进制

posted @ 2022-08-15 22:30  放弃吧  阅读(97)  评论(0编辑  收藏  举报