协程 c语言,协程-C语言实现
最近在学习lua的过程中发现lua居然有个东西叫协程(协同coroutine),虽然以前就听过这个概念,但没有结合实践的一些理解。
开始今天的文章前,首先需要学习下面几篇文章。
Segment Fault例子:
#include
void ping();
void pong();
void ping(){
int a = 0;
printf("ping,addr of a = %p\n",&a);
pong();
}
void pong(){
int b = 0;
printf("pong,addr of b = %p\n",&b);
ping();
}
int main(int argc, char *argv[]){
ping();
return 0;
}
将上述代码编译运行,执行结果:
ping,addr of a = 0x7ffc456b2024
pong,addr of b = 0x7ffc456b2004
ping,addr of a = 0x7ffc456b1fe4
pong,addr of b = 0x7ffc456b1fc4
ping,addr of a = 0x7ffc456b1fa4
pong,addr of b = 0x7ffc456b1f84
ping,addr of a = 0x7ffc456b1f64
pong,addr of b = 0x7ffc456b1f44
ping,addr of a = 0x7ffc456b1f24
pong,addr of b = 0x7ffc456b1f04
ping,addr of a = 0x7ffc456b1ee4
pong,addr of b = 0x7ffc456b1ec4
ping,addr of a = 0x7ffc456b1ea4
pong,addr of b = 0x7ffc456b1e84
ping,addr of a = 0x7ffc456b1e64
pong,addr of b = 0x7ffc456b1e44
ping,addr of a = 0x7ffc456b1e24
pong,addr of b = 0x7ffc456b1e04
ping,addr of a = 0x7ffc456b1de4
pong,addr of b = 0x7ffc456b1dc4
ping,addr of a = 0x7ffc456b1da4
pong,addr of b = 0x7ffc456b1d84
ping,addr of a = 0x7ffc456b1d64
pong,addr of b = 0x7ffc456b1d44
ping,addr of a = 0x7ffc456b1d24
pong,addr of b = 0x7ffc456b1d04
ping,addr of a = 0x7ffc456b1ce4
pong,addr of b = 0x7ffc456b1cc4
ping,addr of a = 0x7ffc456b1ca4
pong,addr of b = 0x7ffc456b1c84
ping,addr of a = 0x7ffc456b1c64
pong,addr of b = 0x7ffc456b1c44
ping,addr of a = 0x7ffc456b1c24
pong,addr of b = 0x7ffc456b1c04
ping,addr of a = 0x7ffc456b1be4
pong,addr of b = 0x7ffc456b1bc4
ping,addr of a = 0x7ffc456b1ba4
pong,addr of b = 0x7ffc456b1b84
Segmentation fault (core dumped)
运行10几秒左右后,程序core dumped,无限递归调用,栈耗尽。可以看到a与b的地址每次调用都不相同。
#include
#include
#define MAX_COUNT (1<<30)
static ucontext_t uc[3];
static int count = 0;
void ping();
void pong();
void ping(){
int a = 10;
while(count < MAX_COUNT){
printf("ping %d,addr of a = %p\n", ++count,&a);
// yield to pong
swapcontext(&uc[1], &uc[2]); // 保存当前context于uc[1],切换至uc[2]的context运行
}
}
void pong(){
int b = 10;
while(count < MAX_COUNT){
printf("pong %d,addr of b = %p\n", ++count,&b);
// yield to ping
swapcontext(&uc[2], &uc[1]);// 保存当前context于uc[2],切换至uc[1]的context运行
}
}
char st1[8192];
char st2[8192];
int main(int argc, char *argv[]){
// initialize context
getcontext(&uc[1]);
getcontext(&uc[2]);
uc[1].uc_link = &uc[0]; //表示uc[1]运行完成后,会跳至uc[0]指向的context继续运行
uc[1].uc_stack.ss_sp = st1; // 设置新的堆栈
uc[1].uc_stack.ss_size = sizeof st1;
makecontext (&uc[1], ping, 0);
uc[2].uc_link = &uc[0]; //表示uc[2]运行完成后,会跳至uc[0]指向的context继续运行
uc[2].uc_stack.ss_sp = st2; // 设置新的堆栈
uc[2].uc_stack.ss_size = sizeof st2;
makecontext (&uc[2], pong, 0);
// start ping-pong
swapcontext(&uc[0], &uc[1]); // 将当前context信息保存至uc[0],跳转至uc[1]保存的context去执行
//swapcontext函数会将当前点的信息保存在uc[0]中,当然我们没有设置的话,默认的堆栈一定是主堆栈啦
return 0;
}
编译运行结果:
ping 332825,addr of a = 0x561022043b14
pong 332826,addr of b = 0x561022041b14
ping 332827,addr of a = 0x561022043b14
pong 332828,addr of b = 0x561022041b14
ping 332829,addr of a = 0x561022043b14
pong 332830,addr of b = 0x561022041b14
ping 332831,addr of a = 0x561022043b14
pong 332832,addr of b = 0x561022041b14
ping 332833,addr of a = 0x561022043b14
pong 332834,addr of b = 0x561022041b14
ping 332835,addr of a = 0x561022043b14
pong 332836,addr of b = 0x561022041b14
ping 332837,addr of a = 0x561022043b14
pong 332838,addr of b = 0x561022041b14
ping 332839,addr of a = 0x561022043b14
pong 332840,addr of b = 0x561022041b14
ping 332841,addr of a = 0x561022043b14
pong 332842,addr of b = 0x561022041b14
ping 332843,addr of a = 0x561022043b14
pong 332844,addr of b = 0x561022041b14
ping 332845,addr of a = 0x561022043b14
pong 332846,addr of b = 0x561022041b14
ping 332847,addr of a = 0x561022043b14
pong 332848,addr of b = 0x561022041b14
ping 332849,addr of a = 0x561022043b14
可以看到a b的地址每次都相同,而不是每次函数调用,使用新的栈地址空间。
#include
#include
#include
int main(int argc, char *argv[])
{
ucontext_t context;
getcontext(&context);
puts("Hello world");
sleep(1);
setcontext(&context);
return 0;
}
getcontext, setcontext - get or set the user context(man setcontext)
这个函数会不断地打印Hello,world。因为上面的getcontext函数将那个点的上下文信息保存到了context中,下面调用setcontext会返回到记录的点处继续执行,因此也就出现了不断地输出。
有了上面的一些理解,我们可以学习一些开源库。(按照代码量从低到高学习)
协程 c语言,协程-C语言实现相关推荐
- go语言协程和线程区别
go语言协程和线程区别 一.线程和协程区别 主线程是一个物理线程,直接作用在 cpu 上的.是重量级的,非常耗费 cpu 资源. Go 主线程(/也可以理解成进程)一个 Go 线程上,可以起多个协程. ...
- python 协程_Python 协程与 Go 协程的区别(一)
? "Python猫" ,一个值得加星标的公众号 花下猫语:年关将近,不知各位过得怎样?我最近有些忙,收获也挺多,以后有机会分享下.吃饭时间,追了两部剧<了不起的麦瑟尔夫人& ...
- 干货 | 携程基于Quasar协程的NIO实践
作者简介 Ryan,携程Java开发工程师,对高并发.网络编程等领域有浓厚兴趣. IO密集型系统在高并发场景下,会有大量线程处于阻塞状态,性能低下,JAVA上成熟的非阻塞IO(NIO)技术可解决该问题 ...
- python 协程可以嵌套协程吗_Python线程、协程探究(2)——揭开协程的神秘面纱...
一.上集回顾 在上一篇中我们主要研究了python的多线程困境,发现多核情况下由于GIL的存在,python的多线程程序无法发挥多线程该有的并行威力.在文章的结尾,我们提出如下需求: 既然python ...
- 携程基于Quasar协程的NIO实践
IO密集型系统在高并发场景下,会有大量线程处于阻塞状态,性能低下,JAVA上成熟的非阻塞IO(NIO)技术可解决该问题.目前Java项目对接NIO的方式主要依靠回调,代码复杂度高,降低了代码可读性与可 ...
- java 修改最大nio连接数_携程基于Quasar协程的NIO实践
IO密集型系统在高并发场景下,会有大量线程处于阻塞状态,性能低下,JAVA上成熟的非阻塞IO(NIO)技术可解决该问题.目前Java项目对接NIO的方式主要依靠回调,代码复杂度高,降低了代码可读性与可 ...
- python 协程可以嵌套协程吗_Python | 详解Python中的协程,为什么说它的底层是生成器?...
今天是Python专题的第26篇文章,我们来聊聊Python当中的协程. 我们曾经在golang关于goroutine的文章当中简单介绍过协程的概念,我们再来简单review一下.协程又称为是微线程, ...
- lua协程 unity_XLua 之 Lua 协程 与 Unity 协程互通
前言: 最近在摸索用XLua 在 Unity 中进行全Lua 开发.然后就遇到了协程的问题.我想在 Lua 侧开启一个 Unity 的协程,该怎么做呢? 一开始我先去翻 XLua 的文档,我记得之前我 ...
- python携程多核_python 协程
最近对Python中的协程挺感兴趣,这里记录对协程的个人理解. 要理解协程,首先需要知道生成器是什么.生成器其实就是不断产出值的函数,只不过在函数中需要使用yield这一个关键词将值产出.下面来看一个 ...
- python 协程可以嵌套协程吗_Python学习后有哪些方向可以选择?Python有什么好的学习方法吗?(附教程)...
随着人工智能的发展,Python近两年也是大火,越来越多的人加入到Python学习大军,对于毫无基础的人该如何入门Python呢?这里整理了一些个人经验和Python入门教程供大家参考. 如果你是零基 ...
最新文章
- 【go】sdk + idea-plugin 开发工具安装
- UI+UE+UX+区别
- C++(STL):30 ---关联式容器map的operator[]和insert效率对比
- cad在布局怎么调比例_大神们都在用的9个CAD制图技巧,你会用几个?
- mysql手工注入imformation_mysql 简单手工注入
- 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(10)---各种线程同步的集合类...
- mysql数据库密码修改
- 可视化 —— 在线图形绘制
- sklearn.metrics —— 混淆矩阵及其绘制、Accuracy/Precision/Recall/F1-score
- Linux用户管理基本配置命令运用1
- k2p 登录路由器shell失败_斐讯路由器无法进入路由器登录管理界面怎么办
- Linux获取电信超级密码,电信光猫-华为HG8245C获取超级管理员密码
- 2021泰迪杯数据分析技能赛A题:Python实现通讯产品销售和盈利能力分析(含原始数据)
- Xrm.WebApi 多对多关系处理
- c语言程序设计实践万年历,c语言程序设计万年历-20210408030342.docx-原创力文档
- Java飞机大战小游戏练习
- cad画不规则实体_cad画不规则曲线的方法步骤图
- 腾讯物联TencentOS tiny上云初探
- 210127 课内整理
- 区块链在改善网络安全方面的潜力?