美文网首页
linux手册翻译——makecontext(2) swapco

linux手册翻译——makecontext(2) swapco

作者: 蟹蟹宁 | 来源:发表于2021-06-23 09:58 被阅读0次

\color{#A00000}{NAME}
makecontext, swapcontext - 操作用户上下文

\color{#A00000}{SYNOPSIS}

#include <ucontext.h>

void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);
int swapcontext(ucontext_t *restrict oucp,const ucontext_t *restrict ucp);

\color{#A00000}{DESCRIPTION}
在类System V的系统中,在<ucontext.h>中定义了两种数据类型:mcontext_t ,ucontext_t 以及四个函数:getcontext(), setcontext(), makecontext(3),swapcontext(3) 以实现用户级线程在其控制进程中进行上下文切换。mcontext_t 类型依赖于CPU硬件且不透明,ucontext_t 类型是一个至少具有以下字段的结构,详见:ucontext(3) get/setcontext(3)

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

makecontext() 函数修改 ucp 指向的上下文(可以通过调用 getcontext(3) 获得),用于指定上下文执行时的入口点函数。 在调用 makecontext() 之前,调用者必须为此上下文分配一个新堆栈并将其地址分配给 ucp->uc_stack,并定义一个后继上下文并将其地址分配给 ucp->uc_link。
getcontext()获得的上下文保存的栈和入口执行点都是原线程的,makecontext()将会为执行上下文指定新的入口点,但是执行堆栈和后继上下文还需要手动指定。
当此上下文被执行时(使用 setcontext(3) 或 swapcontext()),函数 func 被调用,并在参数argc之后传递的一系列整数 (int) 参数; 调用者必须在 argc 中指定这些参数的数量。 当这个函数返回时,后继上下文(即ucp->uc_link)被调用执行。 如果后继上下文指针为 NULL,则线程退出。
swapcontext()函数将当前上下文保存在 oucp 指向的结构中,然后执行 ucp 指向的上下文。
\color{#A00000}{RETURN VALUE}
成功后,swapcontext() 不会返回。(但是也可能返回,如 oucp 被调用执行,在这种情况下它看起来像是从 swapcontext() 返回 0,但是这与真正意义上的函数返回是不一样。)出现错误时,swapcontext() 返回 -1 并设置 errno 以指示错误。

\color{#A00000}{ERRORS}
ENOMEM
剩余堆栈空间不足。

\color{#A00000}{VERSIONS}
自 2.1 版以来,glibc 中提供了 makecontext() 和 swapcontext()。

\color{#A00000}{ATTRIBUTES}

Interface Attribute Value
makecontext() Thread safety MT-Safe race:ucp
swapcontext() Thread safety MT-Safe race:oucp race:ucp

\color{#A00000}{CONFORMING TO}
SUSv2,POSIX.1-2001。 POSIX.1-2008 删除了 makecontext() 和 swapcontext() 的规范,引用了可移植性问题,并建议重写应用程序以改用 POSIX 线程。

\color{#A00000}{NOTES}
ucp->uc_stack 的解释和 sigaltstack(2) 一样,即这个结构体包含了作为栈使用的内存区域的起始和长度,与栈的增长方向无关。 因此,用户程序不必担心这个方向。

在 int 和指针类型大小相同的体系结构上(例如,x86-32,其中两种类型都是 32 位),您可能能够在 argc 之后将指针作为参数传递给 makecontext()。 但是,这样做并不能保证是可移植的,根据标准是未定义的,并且不适用于指针大于整数的体系结构。 尽管如此,从 2.8 版开始,glibc 对 makecontext() 进行了一些更改,以允许在某些 64 位架构(例如 x86-64)上执行此操作。
\color{#A00000}{EXAMPLES}
下面的示例程序演示了 getcontext(3)、makecontext() 和 swapcontext() 的使用。 运行该程序会产生以下输出:

$ ./a.out
main: swapcontext(&uctx_main, &uctx_func2)
func2: started
func2: swapcontext(&uctx_func2, &uctx_func1)
func1: started
func1: swapcontext(&uctx_func1, &uctx_func2)
func2: returning
func1: returning
main: exiting

源代码:

#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>

static ucontext_t uctx_main, uctx_func1, uctx_func2;

#define handle_error(msg) \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)

static void
func1(void)
{
    printf("func1: started\n");
    printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
    if (swapcontext(&uctx_func1, &uctx_func2) == -1)
        handle_error("swapcontext");
    printf("func1: returning\n");
}

static void
func2(void)
{
    printf("func2: started\n");
    printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
    if (swapcontext(&uctx_func2, &uctx_func1) == -1)
        handle_error("swapcontext");
    printf("func2: returning\n");
}

int
main(int argc, char *argv[])
{
    char func1_stack[16384];
    char func2_stack[16384];

    if (getcontext(&uctx_func1) == -1)
        handle_error("getcontext");
    uctx_func1.uc_stack.ss_sp = func1_stack;
    uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
    uctx_func1.uc_link = &uctx_main;
    makecontext(&uctx_func1, func1, 0);

    if (getcontext(&uctx_func2) == -1)
        handle_error("getcontext");
    uctx_func2.uc_stack.ss_sp = func2_stack;
    uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
    /* Successor context is f1(), unless argc > 1 */
    uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
    makecontext(&uctx_func2, func2, 0);

    printf("main: swapcontext(&uctx_main, &uctx_func2)\n");
    if (swapcontext(&uctx_main, &uctx_func2) == -1)
        handle_error("swapcontext");

    printf("main: exiting\n");
    exit(EXIT_SUCCESS);
}

相关文章

网友评论

      本文标题:linux手册翻译——makecontext(2) swapco

      本文链接:https://www.haomeiwen.com/subject/vwcmyltx.html