嵌入式操作系统中任务之间的交互与Linux同一进程的不同线程之间的交互完全类似,可以通过全局变量和任务间通信机制两种方法来实现。这种交互包括任务间的数据传递、状态通知和动作同步等等。
任务间通信主要用于以下几个目的:
- 在任务之间,或任务与中断处理程序之间传递数据。
- 共享资源管理。如果一个资源为多个任务、或者任务与中断处理程序所访问,该资源即为共享资源。共享资源可以是一个全局变量、全局数据结构,或者是一个外设,比如GPIO、串口等等。为了保证数据一致性和访问逻辑的完整性,必须保证一个任务、或中断处理程序在访问时的排他性。
- 任务同步。是指不同任务的相关处理按用户设计的先后顺序执行。比如有两个任务:任务A负责从UART接收数据,并放入一块共享数据区,当数据区放满以后,通知任务B,然后进入等待状态;任务B从该共享数据区读取数据,等共享数据区被全部读出以后,通知任务A,然后进入等待状态。图1这样通过任务之间的同步,两个不同任务的操作就可以按设计的顺序执行。
图 1 任务同步
任务间数据传递
第一种方式是通过全局变量进行交互,涉及到多个任务对同一个数据区访问的问题。为了保证数据的一致性,必须通过中断禁止加访问控制(也可以使用信号量等其他操作系统机制,但这实际上是任务间通信了)。这种供多个任务访问的数据区叫临界区(critical section)。与临界区访问相关的问题一直是多任务(线程)编程的梦靥,这种问题往往没有确定的再现方法,而且同一个问题导致的现象也可能多种多样,非常难于定位。而利用操作系统的任务间通信服务,可以有效避免避免临界区访问控制的复杂性,提高系统运行的确定性。
队列传递
另一种方式是采用操作系统的队列(Queue)机制,有的操作系统也叫邮箱(Mailbox)。队列是由多个元素构成的一个有顺序的序列,其中的每个元素叫数据项,也可以叫消息,如图 2所示(以FreeRTOS为例)。