0

0

今天你要来点 protoThread么?

絕刀狂花

絕刀狂花

发布时间:2025-09-19 08:43:01

|

628人浏览过

|

来源于php中文网

原创

今天我们将插入一篇关于底层软件的文章,名为“【硬件篇】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条件成立才继续执行,否则继续等待。

协程条件阻塞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能够节省很多行代码,而且易于阅读,编程思路和效率也得到提高。

相关专题

更多
typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

107

2023.09.26

define的用法
define的用法

define用法:1、定义常量;2、定义函数宏:3、定义条件编译;4、定义多行宏。更多关于define的用法的内容,大家可以阅读本专题下的文章。

335

2023.10.11

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

754

2023.08.22

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

534

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

417

2024.03.13

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

90

2023.09.25

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1027

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

66

2025.10.17

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

微信小程序开发之API篇
微信小程序开发之API篇

共15课时 | 1.2万人学习

Laravel---API接口
Laravel---API接口

共7课时 | 0.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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