上下文跳转之ucontext

简介: 上下文跳转之ucontext

上下文跳转之ucontext

之前有写过基于C语言标准库的跳转:使用setjmp,这里的ucontext算是第二种方法把

setjmp和longjmp

相关函数

  • getcontext
int getcontext(ucontext_t *ucp);

The function getcontext() initializes the structure pointed at by ucp to the currently active context.

getcontext函数将ucp指针指向的结构初始化为当前上下文。

  • setcontext
int setcontext(const ucontext_t *ucp);

The function setcontext() restores the user context pointed at by ucp. A successful call does not return. The context should have been obtained by a call of getcontext(), or makecontext(), or passed as third argument to asignal handler.

函数setcontext会恢复ucp指向的上下文。如果呼叫成功就不会返回。被指向的上下文应该是通过getcontext或者makecontext获得的,或者作为第三个参数传递给信号处理函数。

  • swapcontext
int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);

The swapcontext() function saves the current context in the structure pointed to by oucp, and then activates the context pointed to by ucp.

swapcontext函数将当前上下文保存在oucp指向的结构中,然后激活ucp指向的上下文。

  • makecontext
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);

The makecontext() function modifies the context pointed to by ucp.Before invoking makecontext(), the caller must allocate a new stack for this context and assign its address to ucp->uc_stack, and define a successor context and assign its address to ucp->uc_link.

makecontext函数修改ucp指向的上下文。在调用makecontext之前,调用方必须为该上下文分配一个新堆栈,并将其地址分配给ucp->uc_stack,并定义一个后续上下文,将其地址指定给ucp–>uc_link。

代码演示

#include <stdio.h>
#include <ucontext.h>
#include <fcntl.h>
ucontext_t main_ctx;
ucontext_t func_ctx[3];
int count = 0;
void func1()
{
    while(count++ <= 30)
    {
        printf("func1 begin\r\n");
        swapcontext(&func_ctx[0], &main_ctx);
        printf("func1 end\r\n");
    }
    
}
void func2()
{
    while(count++ <= 30)
    {
        printf("func2 begin\r\n");
        swapcontext(&func_ctx[1], &main_ctx);
        printf("func2 end\r\n");
    }
    
}
void func3()
{
    while(count++ <= 30)
    {
        printf("func3 begin\r\n");
        swapcontext(&func_ctx[2], &main_ctx);
        printf("func3 end\r\n");
    }
    
}
int main()
{
    char stack1[2048] = {0};
    char stack2[2048] = {0};
    char stack3[2048] = {0};
    getcontext(&func_ctx[0]);
    func_ctx[0].uc_stack.ss_size = sizeof(stack1);
    func_ctx[0].uc_stack.ss_sp = stack1;
    func_ctx[0].uc_link = &main_ctx;
    makecontext(&func_ctx[0], func1, 0);
    getcontext(&func_ctx[1]);
    func_ctx[1].uc_stack.ss_sp = stack2;
    func_ctx[1].uc_stack.ss_size = sizeof(stack2);
    func_ctx[1].uc_link = &main_ctx;
    makecontext(&func_ctx[1], func2, 0);
    getcontext(&func_ctx[2]);
    func_ctx[2].uc_stack.ss_sp = stack3;
    func_ctx[2].uc_stack.ss_size = sizeof(stack3);
    func_ctx[2].uc_link = &main_ctx;
    makecontext(&func_ctx[2], func3, 0);
    while(count <= 30)
    {
        swapcontext(&main_ctx, &func_ctx[count%3]);
        count++;
    }
  return 0;
}

运行结果:

代码解析:

从上面的运行截图可以看出,代码会在swapcontex处从arg1上下文切换到arg2上下文。然后会阻塞在那里,直到遇到下一个swapcontext。

总结

ucontext跳转同样适合用于协程,比起setjmp。它的使用更加简单,但是跨平台能力欠缺,比如在windows上就无法执行。

目录
打赏
0
0
0
0
32
分享
相关文章
使用 contextvars 管理上下文变量
使用 contextvars 管理上下文变量
76 0
C# 当前上下文中不存在InitializeComponent()
C#——当前上下文中不存在InitializeComponent()可能原因是:项目文件直接由外部加载进来时可能出现错误。可以先检查xaml文件的开头x:Class=“day27test02.MainWindow”是否是正确的类名。如果不是,改成对应的项目的类即可。这是本人碰到的这种情况通过这种方式得到解决的,仅供参考。
787 1
C# 当前上下文中不存在InitializeComponent()
Uuiapp使用生命周期,路由跳转传参
Uuiapp使用生命周期,路由跳转传参
162 0
请求上下文
请求上下文
109 0
【小程序】跳转时传递多个参数
【小程序】跳转时传递多个参数
130 0
【小程序】跳转时传递多个参数
【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )
【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )
232 0
【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等