C语言 getcontext 系统调用 (ucontext.h) 到底是做什么的



我去年选择了操作系统,在此期间我使用用户上下文(在标头ucontext.h中定义)为项目实现线程调度程序(其中每个线程模拟一个进程)。我正在参加一个讲座,并将讨论用户上下文,我突然想到,尽管去年已经完成了这个项目,但我并不真正了解getcontext系统调用实际上做了什么。

getcontext的手册页指出

将 UCP 指向的结构初始化为当前活动上下文。

它还指出,对于setcontext的论点,如果 ucp 论证

是通过调用 getcontext() 获得的,程序执行继续,就好像这个调用刚刚返回一样。

好的,所以我明白了。

这就是我感到困惑的地方。通常,对于我学习它的方式,要执行上下文切换,需要初始化ucontext_t结构并交换/设置它:

ucontext_t ucp;
ucontext_t oucp;
getcontext(&ucp);
// Initialize the stack_t struct in the ucontext_t struct
ucp.uc_stack.ss_sp = malloc(STACK_SIZE);
ucp.uc_stack.ss_size = STACK_SIZE;
ucp.uc_stack.ss_flags = 0;
ucp.uc_link = /* some other context, or just NULL */;
// Don't block any signals in this context
sigemptyset(&ucp.uc_sigmask);
// Assume that fn is a function that takes 0 arguments and returns void
makecontext(&ucp, fn, 0);
// Perform the context switch. Function 'fn' will be active now
swapcontext(&oucp, &ucp);
// alternatively: setcontext(&ucp);

如果我在较小的程序中省略getcontext,则不会发生任何有趣的事情。在通过用户上下文进行更多上下文切换的较大程序中,我得到一个分段错误,只能通过重新添加getcontext来解决。

getcontext到底是做什么的?为什么我不能只分配一个ucontext_t结构,通过初始化uc_stackuc_sigmask字段来初始化它,并在没有getcontext的情况下调用makecontext?是否有一些必要的初始化getcontext执行而makecontext不执行?

我查看了 x86/linux 架构上 ucontext 的 GNU libc 实现,因此,可能有不同的实现,以下内容不成立。

GNU libc 手册指出:

传递给 makecontext 的 ucp 参数应通过调用 getcontext 来初始化。

如果你在glibc/sysdeps/unix/linux/x86/sys/ucontext.h中查看mcontext_t,就会发现一个指向浮点状态(fpregset_t fpregs)的指针,该状态在getcontext()中初始化,并在setcontext()中再次取消引用。但是,它不是使用 makecontext() 初始化的。我用 GDB 做了一个快速测试,当试图取消引用指向未由 getcontext() 初始化的ucontext_t结构中的浮点上下文的指针时,我在 setcontext() 中遇到了一个段错误:

=> 0x00007ffff784308c <+44>: FLDENV (%RCX)

相关内容

  • 没有找到相关文章

最新更新