前置知识
协程的定义
- 实现在用户态的轻量级线程
- 协程的切换和调度全部发送用户空间,上下文切换效率比比较高,没用用户态向内核态的转变。
- 意义:
- 针对于一个连接一个进程/线程,提高了单进程/线程的并发性,避免了调度开销,并用同步的编码实现了异步编码的性能。
- 针对单进程/线程epoll,一个进程/线程,可能有多个客户端连接,可以将异步的编码方式写成同步的感觉,是整个任务流程变的顺畅,没有割裂感。
三种实现协程的调度实现方式
- 汇编
- setjmp/longjmp
- ucontext簇函数
ucontext函数簇详解
-
ucontext_t 上下文定义
typedef struct ucontext_t //这个结构就是一个上下文的定义 { unsigned long int __ctx(uc_flags); struct ucontext_t *uc_link; //用户层关心 后续需要的执行的上下文 stack_t uc_stack; //用户层关心 栈空间 mcontext_t uc_mcontext; //底层是这个结构 sigset_t uc_sigmask; struct _libc_fpstate __fpregs_mem; } ucontext_t; // 所有参数中,只需要关注uc_link 和 uc_stack两个参数,这两个参数是用户层的 uc_link 指的是当前上下文结束后需要执行的上下文,如果设置为NULL,则表示当前结束后进程退出? 线程呢? uc_stack 中需要指定协程的 栈地址 和 大小
-
getcontext
int getcontext(ucontext_t *ucp); //用于初始化 这个函数用获取当前上下文保存到ucp结构中
-
makecontext
int getcontext(ucontext_t *ucp); //用于初始化 这个函数用获取当前上下文保存到ucp结构中
-
setcontext
void makecontext(ucontext_t *ucp,void(*func)(),int argc,...); //将上下文和函数绑定 这个函数用来修改上下文信息,可以用来设置上下文的入口函数,其中ucp必须经过getcontext初始化 上下文可以和函数绑定,这样切换上下文的话,就会跑到函数里面去执行,这样就实现了一次切换,从A函数切换到B函数
-
swapcontext
int swapcontext(ucontext_t *oucp,ucontext_t *ucp) 该函数用来切换上下文,同时保存当前上下访问到oucp,ucp上下文是由getcontext 和 makecontext设置而来 先保存当前上下文到oucp中,再将当前上下文切换到第二个context上,这样就完成了一次切换,同时保存了当前上下文 相当于getcontext(oucp)再setcontext(ucp);