操作系统编程设计:ucontent


Introduction

前面我们介绍了基于 setjmp/getjmp
控制流的编程方法,下面我们将要介绍更高级的基于ucontent控制流编程方法。通过ucontent,可以实现迭代器( Iterator )、 纤程 ( Fiber )、 协程 ( Coroutine )。

ucontext

首先是最重要的ucontext结构,由context.h或者sys/context.h定义。
/* Userlevel context. */
typedef struct ucontext
{
unsigned long int uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
mcontext_t uc_mcontext;
__sigset_t uc_sigmask;
struct _libc_fpstate __fpregs_mem;
} ucontext_t;
—|—
其中比较重要的:

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的循环程序:
#include <stdio.h>
#include <ucontext.h>
int main() {
ucontext_t context;
getcontext(&context);
printf(“csprojectedu\n”);
setcontext(&context);
return 0;
}
—|—
编译运行程序:
$ gcc ucontextdemo.c -o ucontextdemo
$ ./ucontextdemo
csprojectedu
csprojectedu

发生了什么?

  1. 当程序运行到getcontext时,将当前程序的context保存到context变量中。
  2. 打印csprojectedu。
  3. 程序运行到setcontext,将当前程序的context置为变量context指向的context。
  4. 由于context被重置为之前设置的地方,因此接下来将要打印csprojectedu。

Summary

通过简单的程序,介绍了ucontext的控制流的程序设计方法。由于makecontext可以指定运行的函数以及参数,因此可以编写出更多有意思的程序。
(本文出自 csprojectedu.com
,转载请注明出处)


文章作者: SafePoker
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 SafePoker !
  目录