上下文跳转之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上就无法执行。

相关文章
|
API C++ Windows
自定义跳转函数的通用unhook方法
自定义跳转函数的通用unhook方法
|
3月前
|
安全 Go 开发者
使用 contextvars 管理上下文变量
使用 contextvars 管理上下文变量
58 0
|
7月前
|
小程序
小程序页面路由传参的方法?
小程序页面路由传参的方法?
75 0
|
JavaScript
Uuiapp使用生命周期,路由跳转传参
Uuiapp使用生命周期,路由跳转传参
150 0
|
JavaScript 前端开发 Linux
网页跳转代码的三种方法
网页跳转代码的三种方法
1511 0
|
JavaScript 开发者
指令-自定义全局指令让文本框获取焦点|学习笔记
快速学习指令-自定义全局指令让文本框获取焦点
240 0
指令-自定义全局指令让文本框获取焦点|学习笔记
小程序将跳转传参带对象
先在跳转的页面转成字符串
|
小程序
【小程序】跳转时传递多个参数
【小程序】跳转时传递多个参数
121 0
【小程序】跳转时传递多个参数
|
移动开发 小程序
小程序跳转到h5页面无法获取参数
小程序跳转到h5页面无法获取参数
小程序跳转到h5页面无法获取参数
|
Android开发
【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )
【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )
224 0
【Android 逆向】函数拦截原理 ( 通过修改 GOT 全局偏移表拦截函数 | 通过在实际被调用的函数中添加跳转代码实现函数拦截 )