今天你要来点 protoThread么?

絕刀狂花
发布: 2025-09-19 08:43:01
原创
612人浏览过

今天我们将插入一篇关于底层软件的文章,名为“【硬件篇】vcu软件接口原理”的更新工作仍在进行中,预计将超过10篇,敬请期待。今天我们将探讨一种事件驱动模型“protothreads”,由瑞典sics的adam dunkels开发,并在contiki os中使用。这款模型非常适合资源受限的嵌入式系统,我也曾在某个项目中使用过,深感其妙,愿与大家分享。文中所述可能未尽详尽,欢迎各位指出不足之处。

今天你要来点 protoThread么?protothreads简介

任务

protothreads是一种轻量级的线程模型,其编程风格类似于Windows中的线程,但更倾向于无线程编程。在操作系统中,每个线程都有独立的任务栈,而protothreads的各个线程共享同一个任务栈,从而减少了RAM的使用。

上下文切换:

在protothreads编程模型中,任务本质上是函数,函数之间协同工作,因此也被称为“协程(coroutine)”。上下文切换与操作系统中的不同,操作系统由OS管理上下文切换,而在protothreads模型中,通过yield方式保存现场并转移运行权。

任务阻塞:

protothreads虽然提供了在各自线程内条件阻塞的机制,但对于在该线程内调用的其他函数,则无法阻塞其运行。因此,如果要在线程内调用耗时较长的函数,为确保各个线程的实时性,需要将这些函数进一步分解为更小的函数,分步执行。protothreads的阻塞本质上是函数返回,且只能在程序员指定的位置进行阻塞。

代码分析

protothreads包含5个头文件,是的,你没看错,是头文件,意味着没有C文件,整个模型是通过宏实现的。下表简单描述了这5个头文件的主要内容。

lc-addrlabels.h 使用GCC扩展语法实现的协程基础 lc-switch.h

使用switch语句实现的协程基础

lc.h

用于选择GCC语法还是switch语句实现

pt.h

基于lc.h实现协程API

pt-sem.h

协程间通信(信号量)的实现

主要API包含在pt.h中,以下介绍一些常用的API:

协程初始化代码:#define PT_INIT(pt) LC_INIT((pt)->lc)

解释:初始化一个协程,实际上是初始化状态变量(pt)->lc,类似于MBD模型开发中的各个StateFlow状态;

协程入口代码:

#define PT_BEGIN(pt) \

{ char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)

解释:协程的入口,PT_YIELD_FLAG =1,表示不让出运行权,PT_YIELD_FLAG =0表示让出运行权,LC_RESUME就是跳转到上一次让出运行权的位置继续运行,本质上是switch跳转到相应的case。

协程的退出口代码:

#define PT_END(pt) \

LC_END((pt)->lc); PT_YIELD_FLAG = 0; \

PT_INIT(pt); return PT_ENDED; }

解释:协程的退出口,到此一个协程结束,内容就是清除标志和上下文状态。

协程条件阻塞1代码:

#define PT_WAIT_UNTIL(pt, condition)\

do {\

LC_SET((pt)->lc);\

if(!(condition)) {\

return PT_WAITING;\

}\

} while(0)

解释:协程条件阻塞,阻塞的本质是让出CPU运行权,首先记录下当前的状态(LC_SET((pt)->lc)),以便下一次恢复,保存现场后再判断条件,如果condition为真,则继续往下运行,如果condition为假,直接return返回函数状态PT_WAITING,让出运行权,保持阻塞状态。所以可以这样理解:直到condition条件成立才继续执行,否则继续等待。

火山写作
火山写作

字节跳动推出的中英文AI写作、语法纠错、智能润色工具,是一款集成创作、润色、纠错、改写、翻译等能力的中英文 AI 写作助手。

火山写作 166
查看详情 火山写作

协程条件阻塞2代码:

#define PT_WAIT_WHILE(pt,condition) \

PT_WAIT_UNTIL((pt), !(condition))

解释:类似PT_WAIT_UNTIL,只是condition的条件取反。可以这样理解:当condition条件成立时继续等待,否则继续执行。

协程退出代码:

#define PT_EXIT(pt)\

do {\

PT_INIT(pt);\

return PT_EXITED;\

} while(0)

解释:任务后面的代码不执行,初始化状态变量,然后直接退出重新执行。

协程无条件让出运行权代码:

#define PT_YIELD(pt)\

do {\

PT_YIELD_FLAG = 0;\

LC_SET((pt)->lc);\

if(PT_YIELD_FLAG == 0) {\

return PT_YIELDED;\

}\

} while(0)

解释:协程运行权无条件让出一次,让出前,先记录下当前的状态(LC_SET((pt)->lc)),以便下一次恢复,保存现场后,立即让出运行权,本质上是函数return。

协程有条件让出运行权代码:

#define PT_YIELD_UNTIL(pt,condition)\

do {\

PT_YIELD_FLAG = 0;\

LC_SET((pt)->lc);\

if((PT_YIELD_FLAG == 0) || !(condition)) {\

return PT_YIELDED;\

}\

} while(0)

解释:比PT_YIELD(pt)多了一个条件,协程运行权首先无条件让出一次,这是通过PT_YIELD_FLAG来实现的,第二次运行时,再判断条件condition,如果条件为真,继续执行,如果条件为假,则立即让出运行权继续阻塞。

实例

上面介绍了常用API,下面我们看一个实例:

今天你要来点 protoThread么? 上面的代码就不多解释了,注释已经写得很详细了,唯一需要解释的是这个宏“PT_WAIT_MS”,这是我通过PT_WAIT_UNTIL扩展出来的API,并结合系统Tick实现了延时功能。如果大家熟悉使用后,也可以利用基础的API去扩展自己的功能API。

大家不难发现,相对于使用状态机去实现同样的功能,使用protothreads能够节省很多行代码,而且易于阅读,编程思路和效率也得到提高。

以上就是今天你要来点 protoThread么?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号