Introduction
前面我们介绍了基于setjmp/getjmp控制流的编程方法,下面我们将要介绍更高级的基于ucontent控制流编程方法。通过ucontent,可以实现迭代器(Iterator)、纤程(Fiber)、协程(Coroutine)。
ucontext
首先是最重要的ucontext结构,由context.h或者sys/context.h定义。
1 | /* Userlevel context. */ |
其中比较重要的:
uc_link:当前context退出后,指向下一个要运行的context的指针
uc_stack:用于当前context的栈空间
uc_mcontext:用于保存当前context状态,具体来讲是所有寄存器的值
uc_sigmask:保存阻塞在当前context中信号
makecontext
makecontext的函数原型为:
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
makecontext将当前context修改为ucp指向的context,在使用makecontext前,需要为ucp->uc_stack分配新的栈空间,以及为ucp->uc_link分配下一个context,以指定当前context结束后的下一个context地址。
swapcontext
swapcontext的函数原型为:
int swapcontext(ucontext_t *oucp, ucontext_t *ucp);
swapcontext将当前context保存在oucp中,并且执行ucp指向的context。
若swapcontext执行成功,不返回任何值(因为context已经改变),仅执行错误时返回。
getcontext
getcontext的函数原型为:
int getcontext(ucontext_t *ucp);
getcontext将ucp指向的context设置为当前context。
仅当ucp为NULL时,函数会失败。
setcontext
setcontext的函数原型为:
int setcontext(const ucontext_t *ucp);
setcontext将当前context保存到ucp指向的context中。
若setcontext执行成功,不返回任何值(因为context已经改变),仅执行错误时返回。
Example
下面给出一个使用getcontext/setcontext的循环程序:
1 |
|
编译运行程序:
$ gcc ucontextdemo.c -o ucontextdemo$ ./ucontextdemocsprojecteducsprojectedu...
发生了什么?
- 当程序运行到getcontext时,将当前程序的context保存到context变量中。
- 打印csprojectedu。
- 程序运行到setcontext,将当前程序的context置为变量context指向的context。
- 由于context被重置为之前设置的地方,因此接下来将要打印csprojectedu。
Summary
通过简单的程序,介绍了ucontext的控制流的程序设计方法。由于makecontext可以指定运行的函数以及参数,因此可以编写出更多有意思的程序。
(本文出自csprojectedu.com,转载请注明出处)