协程基础_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(); ...
随机推荐
- 什么时候该用 Apache Kafka
rabbitMQ kafka https://coyee.com/article/12091-understanding-when-to-use-rabbitmq-or-apache-kafka Ap ...
- python的算法:二分法查找(2)--bisect模块
Python 有一个 bisect 模块,用于维护有序列表.bisect 模块实现了一个算法用于插入元素到有序列表.在一些情况下,这比反复排序列表或构造一个大的列表再排序的效率更高.Bisect 是二 ...
- ORACLE中通过DBMS_CRYPTO包对表敏感字段进行加密
http://doc.primeton.com/pages/viewpage.action?pageId=4917998
- MYSQL的内外连接
1.内联接(典型的联接运算,使用像 = 或 <> 之类的比较运算符).包括相等联接和自然联接. 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 stude ...
- 用LoopBack搭建RESTful 风格的API
1.安装node.NPM 2.安装strongloop npm install -g --unsafe-perm install strongloop 3.创建工作目录并且配置loopback应用 m ...
- configure.ac中AC_CHECK_LIB的问题
编译Linux程序时,使用configure.ac生成的configure程序,时常会出现AC_CHECK_LIB检查某个库失败 而相应库通常是存在的,只是依赖于其他的库,此时,需要乃至AC_CHEC ...
- 数据排序 第二讲( 各种排序方法 结合noi题库1.10)
先来个题练练手吧! 例题 04:奖学金 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生 ...
- [BZOJ 2395] Time is money
Link: BZOJ 2395 传送门 Solution: 算是一类比较经典的模型: 即对于一类经典问题,每点由1个权值化为2个权值,最终求$sigma(val_1)*sigma(val_2)$ 对于 ...
- Codeforces 919 E Congruence Equation
题目描述 Given an integer xx . Your task is to find out how many positive integers nn ( 1<=n<=x1&l ...
- BZOJ 1852 [MexicoOI06]最长不下降序列(贪心+DP+线段树+离散化)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1852 [题目大意] 给你N对数A1,B1……An,Bn.要求你从中找出最多的对, 把它 ...