setcontext(2) - Linux 手册页
名称
getcontext, setcontext - 获取或设置用户上下文
概要
#include <ucontext.h>
int getcontext(ucontext_t *ucp);
int setcontext(const ucontext_t *ucp);
描述
在类似 System V 的环境中,定义了两种类型 mcontext_t 和 ucontext_t,它们位于 <ucontext.h> 中,以及四个函数 getcontext()、setcontext()、makecontext(3) 和 swapcontext(3),它们允许在进程内的多个控制线程之间进行用户级别的上下文切换。
mcontext_t 类型是机器相关的且不透明的。ucontext_t 类型是一个结构体,至少包含以下字段
-
typedef struct ucontext { struct ucontext *uc_link; sigset_t uc_sigmask; stack_t uc_stack; mcontext_t uc_mcontext; ... } ucontext_t; - 同时定义了 sigset_t 和 stack_t,它们位于 <signal.h> 中。这里 uc_link 指向当前上下文终止时将要恢复的上下文(如果当前上下文是使用 makecontext(3) 创建的),uc_sigmask 是此上下文中屏蔽的信号集(参见 sigprocmask(2)),uc_stack 是此上下文使用的堆栈(参见 sigaltstack(2)),而 uc_mcontext 是保存上下文的机器特定的表示形式,其中包含调用线程的机器寄存器。
函数 getcontext() 将指向 ucp 的结构体初始化为当前活动上下文。
函数 setcontext() 恢复由 ucp 指向的用户上下文。 成功调用不会返回。 该上下文应该通过调用 getcontext() 或 makecontext(3) 获得,或者作为信号处理程序的第三个参数传递。
如果上下文是通过调用 getcontext() 获得的,程序执行将继续,就像此调用刚刚返回一样。
如果上下文是通过调用 makecontext(3) 获得的,则程序执行将通过调用作为该调用 makecontext(3) 的第二个参数指定的函数 func 继续。 当函数 func 返回时,我们将继续使用结构体 ucp 的 uc_link 成员,该结构体是作为对该调用 makecontext(3) 的第一个参数指定的。 当此成员为 NULL 时,线程将退出。
如果上下文是通过调用信号处理程序获得的,那么旧的标准文本指出“程序执行将继续执行被信号中断的指令之后的程序指令”。但是,该句子在 SUSv2 中已被删除,目前的结论是“结果未指定”。
返回值
成功时,getcontext() 返回 0,而 setcontext() 不会返回。发生错误时,两者都返回 -1 并适当地设置 errno。
错误
未定义。
符合
SUSv2, POSIX.1-2001。POSIX.1-2008 删除了 getcontext() 的规范,理由是可移植性问题,并建议应用程序重写为使用 POSIX 线程。
说明
这种机制的最早形式是 setjmp(3)/longjmp(3) 机制。 由于它没有定义信号上下文的处理方式,下一个阶段是 sigsetjmp(3)/siglongjmp(3) 对。 现在的机制提供了更多的控制。 另一方面,没有简单的方法来检测从 getcontext() 的返回是来自第一次调用,还是通过 setcontext() 调用。 用户必须发明她自己的簿记设备,而寄存器变量不起作用,因为寄存器会被恢复。
当发生信号时,当前用户上下文被保存,内核为信号处理程序创建一个新的上下文。 不要使用 longjmp(3) 离开处理程序:如果使用上下文会发生什么是不确定的。 而是使用 siglongjmp(3) 或 setcontext()。
参见
sigaction(2), sigaltstack(2), sigprocmask(2), longjmp(3), makecontext(3), sigsetjmp(3)