POSIX的协程/纤程库

2021-06-23  本文已影响0人  蟹蟹宁

为支持纤程,POSIX的<ucontext.h>头文件中定义了4个操作函数以及一个结构体,以允许在用户级实现在进程中切换线程的上下文,更加确切的说法应该是,实现多对一的用户线程和内核线程。
一个结构体:ucontext_t
4个操作:get/set/make/swap context

结构体:ucontext_t

ucontext_t至少包括一下字段:

typedef struct ucontext_t{
        struct ucontext_t* uc_link;
        sigset_t          uc_sigmask;
        stack_t           uc_stack;
        mcontext_t     uc_mcontect;    
        ...
}

mcontext是依赖于不同的硬件机器,且不透明。
uc_ink指向了当前上下文终止时将恢复的上下文(若此上下文是由makecontext创建的),uc_sugmask是该上下文信号集的阻塞信号集,uc_stack是context堆栈;uc_mcontext则用于记录机器寄存器的信息。

函数体

int getcontext(ucontext_t*ucp);
int setcontext(const ucontext_t*ucp);

getcontex()函数将ucp指向的结构体系初始为当前活动的context,而setcontext()则是将当前上下文恢复为ucp所指的上下文,成功调用setcontext()后将不会返回。

getcontest (&UC);
printf (“hello”);
setcontext (&ucp);

此过程是一个死循环且整个过程没有进行堆栈的切换

如果context是通过getcontext获得,那么协程将从getcontext()的返回点继续执行,就像刚从函数返回。
如果context是通过makecontext()产生,协程将从其第2位参数func开始执行,当func执行结束时将执行ucp的第1个参数指定的协程,直到uc_link位NULL,线程结束。
从描述上可以知道makecontext()新创建了堆栈,并在堆栈中压入了uc_link的地址,或一个go_exit类似的处理函数,从而实现上述过程,而getcontext()继承了原堆栈

void makecontext(ucontext*ucp,void(*func)(),int argc,...)
int swapcontext(ucontext*oucp,ucontext*ucp)

makecontext()用于修改ucp的值,ucp是通过getcontext()获取的。(直接调用makecontext()会报错)在调用此函数之前需要指定uc_stack和uc_link。
当此context被activated之后,将会调用func执行,并传递一系列整型参数,由arge指定参数的个数。
swapcontext会保存当留状态到oucp,并切换到新的ucp中。

上一篇下一篇

猜你喜欢

热点阅读