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

相关文章
|
编解码 自然语言处理 算法
开源版图生视频I2VGen-XL:单张图片生成高质量视频
VGen是由阿里巴巴通义实验室开发的开源视频生成模型和代码系列,具备非常先进和完善的视频生成系列能力
|
存储 网络协议
TCP服务器 IO多路复用的实现:select、poll、epoll
TCP服务器 IO多路复用的实现:select、poll、epoll
475 0
|
缓存 负载均衡 网络协议
网络协议之:sctp流控制传输协议
要讲网络协议,肯定离不开OSI(Open System Interconnection)的七层模型。 我们一般关注的是网络层之上的几层,比如IPV4 IPV6所在的网络层,TCP UDP所在的传输层,HTTP FTP所在的应用层等。
网络协议之:sctp流控制传输协议
|
JavaScript Linux 编译器
c++开源协程库libgo介绍及使用
c++开源协程库libgo介绍及使用
|
前端开发 程序员 调度
探索协程在 C++ 中的实现方式
探索协程在 C++ 中的实现方式
504 2
|
程序员 Linux 调度
用ucontext库创建简单的协程
用ucontext库创建简单的协程
377 0
|
应用服务中间件 Linux nginx
Mac Nginx 配置文件使用(nginx.conf,包含M系列)
Mac Nginx 配置文件使用(nginx.conf,包含M系列)
1373 0
|
Shell C++
鼠标右键打开 VSCode 设置(Open With VSCode)(二)
鼠标右键打开 VSCode 设置(Open With VSCode)(二)
|
数据安全/隐私保护
PCIe ARI (Alternative Routing-ID Interpretation)介绍
PCIe ARI (Alternative Routing-ID Interpretation)介绍
3281 0
PCIe ARI (Alternative Routing-ID Interpretation)介绍
下一篇
开通oss服务