嵌入式软件编程中的异步、同步非阻塞、同步阻塞的对比
https://blog.csdn.net/zoomdy/article/details/90056185
mingdu.zheng at gmail dot com
异步
异步的执行效率是最高的,中断就是异步的,中断驱动比轮询驱动的效率高,这毋庸置疑。然而,异步程序的设计也是最困难的,状态的存储问题、代码分散的问题、控制反转的问题,每个问题都很棘手。
异步可以高效地实现任务并发,异步实现并发很省时钟,也很省 RAM,就是比较费脑子,对 ROM 的需求是略微增多的,因为异步编程会产生很多小函数,还不能做内联等优化,因为这些小函数要作为回调函数来使用。
同步阻塞
同步阻塞是最简单的,最符合人的思维习惯的,也符合过程式语言(例如C语言)的使用习惯。阻塞的情况分三种:
- 有操作系统的支持,那么阻塞时可以挂起当前任务去执行其它任务。这种情况下,虽然时钟没有被浪费掉,但是每个任务都需要独立的堆栈空间,这会增大对 RAM 的需求。
- 裸机环境下,阻塞时执行繁忙等待,这种情况下,CPU 是在空转,白白浪费了时钟,也白白浪费了能量。
- 裸机环境下,阻塞时进入休眠,等待中断来唤醒,这种情况下,浪费了时钟,但节省了能量,不过在设计上要多一些工作,唤醒也是要配置过的。
同步阻塞只有在操作系统的支持下才能够实现任务并发,并发的任务越多,需要越多的 RAM;没有操作系统的情况下不能实现并发。
同步非阻塞
同步非阻塞则是执行效率和设计简单性的一个折中。首先,它是同步的,符合程序的编写习惯,其次,它是非阻塞的,当外设没有准备就绪时,它不会死等,而是去执行其它任务或进入休眠。
同步非阻塞可以实现任务并发,其执行效率比异步略低,因为要经常来轮询一下外设的情况,如果外设仍然没有准备就绪,那么当前这次轮询是浪费的,而异步是外设准备就绪的情况下才会执行回调函数。但明显高于同步阻塞。
同步非阻塞的实现需要借助状态机,这点与异步编程类似。可以设计显式的状态机,但是这不容易,设计显式的状态机,首先要对状态机建模,确定状态机的状态以及迁移等,然后就是繁复的编码。不过,可以借助协程库(例如 Protothreads)来创建隐式状态机,借助协程可以将同步非阻塞的设计编码成同步阻塞那样直观,本质上程序是按同步非阻塞执行的,但代码看起来就像是同步阻塞一样,借助协程可以大大简化同步非阻塞的设计和编码。