协程基础_context系列函数
近期想看看协程,对这个的详细实现不太了解。查了下,协程最常规的做法就是基于makecontext,getcontext,swapcontext这类函数在用户空间切换用户上下文。
所以在这通过样例代码尽量把context相关的函数弄清楚先。
#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"); //4
printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n"); //5
if (swapcontext(&uctx_func1, &uctx_func2) == -1) //切换回func2运行
handle_error("swapcontext");
printf("func1: returning\n"); //7
} static void
func2(void)
{
printf("func2: started\n"); //2
printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n"); //3
if (swapcontext(&uctx_func2, &uctx_func1) == -1) //切换到func1运行
handle_error("swapcontext");
printf("func2: returning\n"); //6
} int
main(int argc, char *argv[])
{ //注意在实际中要注意stack大小,否则可能会出现溢出.
char func1_stack[16384];
char func2_stack[16384]; //获取当前进程/线程上下文信息,存储到uctx_func1中
if (getcontext(&uctx_func1) == -1)
handle_error("getcontext"); //uc_stack: 分配保存协程数据的堆栈空间
uctx_func1.uc_stack.ss_sp = func1_stack; //栈头指针
uctx_func1.uc_stack.ss_size = sizeof(func1_stack); //栈大小
uctx_func1.uc_link = &uctx_main; //协程兴许的context
makecontext(&uctx_func1, func1, 0); //依改动得到一个新的centext 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 */
//假设argc有传參数进来,则uc_link置为空.兴许代码将不再运行
uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
makecontext(&uctx_func2, func2, 0); printf("main: swapcontext(&uctx_main, &uctx_func2)\n"); //1
//swapcontext(ucontext_t *oucp, ucontext_t *ucp)
// 进行上下文切换。将当前上下文保存到oucp中,切换到ucp
//将当前上下文保存到uctx_main, 并切换到uctx_func2
if (swapcontext(&uctx_main, &uctx_func2) == -1)
handle_error("swapcontext"); printf("main: exiting\n"); //8 : 如argc不为空则这不会运行.
exit(EXIT_SUCCESS);
}
样例执行结果:
suora:/test # ./co1 5
main: swapcontext(&uctx_main, &uctx_func2)
func2: started
func2: swapcontext(&uctx_func2, &uctx_func1)
func1: started
func1: swapcontext(&uctx_func1, &uctx_func2)
func2: returning
suora:/test # ./co1
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
从执行结果看,大致弄清这几个函数了,只是我对stack大小还是没弄清楚应当怎么估算,但我把这个样例再实现了下。
弄了个动态分配内存的试了试。
/*************************************************
Author: xiongchuanliang
Description: coroutine suora:/test # gcc -o co2 co2.c
suora:/test # ./co2
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
suora:/test # ./co2 3 5
main: swapcontext(&uctx_main, &uctx_func2)
func2: started
func2: swapcontext(&uctx_func2, &uctx_func1)
func1: started
func1: swapcontext(&uctx_func1, &uctx_func2)
func2: returning
suora:/test #
**************************************************/ #include <ucontext.h>
#include <stdio.h>
#include <stdlib.h> ucontext_t uctx_main, uctx_func1, uctx_func2; #define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0) #define CONTEXT_STACK (1024*64) // 64kB
typedef void (*context_func)(void); void func1(void);
void func2(void); int ctx_create(ucontext_t *ctx,
context_func func,
ucontext_t *ctx_link,
void *ss_sp,
size_t ss_size); int main(int argc, char *argv[])
{
if(ctx_create(&uctx_func1,func1,&uctx_main,
malloc(CONTEXT_STACK),CONTEXT_STACK) == 1)
return EXIT_FAILURE; if(ctx_create(&uctx_func2,func2,
(argc > 1) ? NULL : &uctx_func1 , //&uctx_func1
malloc(CONTEXT_STACK),CONTEXT_STACK) == 1)
{
free( uctx_func1.uc_stack.ss_sp );
return EXIT_FAILURE;
} printf("main: swapcontext(&uctx_main, &uctx_func2)\n"); if (swapcontext(&uctx_main, &uctx_func2) == -1)
handle_error("swapcontext"); free( uctx_func1.uc_stack.ss_sp );
free( uctx_func2.uc_stack.ss_sp ); printf("main: exiting\n");
exit(EXIT_SUCCESS);
} int ctx_create(ucontext_t *ctx,
context_func func,
ucontext_t *ctx_link,
void *ss_sp,
size_t ss_size)
{
if(getcontext(ctx) == -1)
{
handle_error("getcontext");
return 1;
}
ctx->uc_link = ctx_link;
ctx->uc_stack.ss_sp = ss_sp;
ctx->uc_stack.ss_size = ss_size;
ctx->uc_stack.ss_flags = 0; makecontext(ctx, func, 0);
return 0;
} 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");
} 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");
}
今天先弄到这.
MAIL: xcl_168@aliyun.com
BLOG: blog.csdn.net/xcl168
协程基础_context系列函数的更多相关文章
- Kotlin协程基础
开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 我们已经通过第一个例子学会了启 ...
- pyhon——进程线程、与协程基础概述
一直以来写博客都是实用主义者,只写用法,没信心写原理,但是每一次写作业的过程都有一种掘地三尺的感觉,终于,写博客困难症重症患者经历了漫长的思想斗争,还是决定把从网上淘到的各种杂货和自己的总结放在一起, ...
- Lua的协程基础
参考:Lua中的协同程序 coroutine http.lua 协同程序(Coroutine): 三个状态:suspended(挂起,协同刚创建完成时或者yield之后).running(运行). ...
- [golang note] 协程基础
协程概念 √ 协程通常称为coroutine,在golang中称为goroutine. √ 协程本质上是一种用户态线程,它不需要操作系统来进行抢占式调度,在实际实现中寄存在线程之中. √ 协程系统开销 ...
- 数据库 tcp协程实现并发 回调函数
数据库 tcp协程实现并发 回顾 一.回顾 进程池,线程池,回调函数 # from gevent import monkey;monkey.patch_all() #补丁 from gevent im ...
- Unity协程基础用法
//通过StartCoroutine()开始一个协程//通过StopCoroutine();关闭一个协程//通过StopAllCoroutines()方法来实现关闭所有协程void Start(){D ...
- 协程(Coroutines)实现fibonacci函数
def fibonacci(): yield 1 yield 1 l=[1,1] while True: l=[l[-1],sum(l[-2:])] yield l[-1] def tribonacc ...
- Kotlin协程解析系列(上):协程调度与挂起
vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...
- Unity3d 协程、调用函数、委托
(一)协程 开启方法:StartCoroutine("函数名"): 结束方法StopCoroutine("函数名"),StopAllCoroutines(); ...
随机推荐
- Spring -- 注解事务 以及 7个传播行为
注解事务: 1.开启注解事务配置: <!-- 事务管理器 --> <bean id="transactionManager" class="org.sp ...
- 某dp题2
P2401 不等数列 题目描述 将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入">"和"<".问在所有排列中,有多少个排列恰好有k ...
- MySQL InnoDB MVCC深度分析
关于MySQL的InnoDB的MVCC原理,很多朋友都能说个大概: 每行记录都含有两个隐藏列,分别是记录的创建时间与删除时间 每次开启事务都会产生一个全局自增ID 在RR隔离级别下 INSERT -& ...
- DB2、ORACLE SQL写法的主要区别
DB2.ORACLE SQL写法的主要区别 说实话,ORACLE把国内的程序员惯坏了,代码中的SQL充斥着大量ORACLE特性,几乎没人知道ANSI的标准SQL是什么样子,导致程序脱离了ORACL ...
- Asp.net中的一个判断session是否合法的做法
1 if (Session["UserID"] == "" || Session["UserID"] == null) 2 { 3 ...
- 【转】appium常用方法整理
1.相对坐标解锁九宫格 应用场景 QQ解锁屏幕如上,可见九个按键在同一个View下面,要实现解锁,用press moveTo release perform方法 实现代码如下: WebElem ...
- 7/26 CSU-ACM2018暑期训练3-递归&递推-选讲
题目链接 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= ...
- Codeforces Round 251 (Div. 2)
layout: post title: Codeforces Round 251 (Div. 2) author: "luowentaoaa" catalog: true tags ...
- 表(Table)
虽然我们已经将不同用途的物品保存在不同的仓库中了,但是在同一个仓库中数据的保存仍然存在问题.比如食品分为熟食.生肉.大米等,如果把他们随意的堆放在一起,就会造成我们无法很容易的对这些食品进行管理,当要 ...
- [BZOJ3944]Sum(杜教筛)
3944: Sum Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6201 Solved: 1606[Submit][Status][Discuss ...