目录
一、概述与信号量
多任务系统中任务之间/任务与中断服务ISR的关系是
- 相互独立:仅竞争CPU资源
- 互斥:竞争除CPU之外的其他公共资源(任务间互斥的是全局变量或者共享内存)
- 同步:协调彼此运行的步调,保证协同运行的各个任务具有正确的执行次序
- 通信:彼此间传递数据或信息,以协同完成某项工作
1.1 概述
同步(通信)的基本方式:分为任务与任务,任务和中断之间进行同步通信。通信分为单向和双向,双向之间的通信仅存在任务之间,因为ISR不可以进行等待 。
同步主要机制和应用:在单处理器平台上,嵌入式OS内核主要提供同步、互斥与通信机制。主要包括
- 信号量(semaphore):用于互斥与同步。
- 事件:用于同步;
- 邮箱(mailbox)、消息队列(message queue):用于消息通信。
- 异步信号(asynchronous signal):用于同步;
- 管道(pipe):提供非结构化数据交换(通信)和实现同步。
单处理器或者多处理器系统中,还有其他一些机制也可以用于同步与通信:全局变量、共享内存、Sockets、远程过程调用(Remote Procedure Call, RPC)。
1.2 信号量概述
信号量用于实现任务与任务之间、任务与中断处理程序之间的同步与互斥。信号量分为三类互斥信号量、二值信号量、计数信号量。
(1)互斥信号量:用于解决互斥问题,可能会引起优先级反转问题。用改信号量保护的代码区称为“临界区”,临界区代码通常用于对共享资源的访问。共享资源可能是一段内存,一个数据结构,I/O设备,也可以是被两个或者多个任务共享的任何内容。使用互斥信号量可以实现对共享资源的串行访问,保证只有成功的获取互斥信号量的任务才能够释放它。
互斥信号量基本特点是互斥信号量的值被初始化为1(表示资源可用),最多只有一个任务可以进入“临界区”,当有任务成功获取互斥信号量之后,值变为0。以下是互斥信号量状态图
互斥信号量是一种特殊的二值信号量,一般它支持所有权、递归访问、任务删除安全和一些避免优先级反转、饿死、死锁等互斥所固有的协议。
所有权指当一个任务通过获取互斥信号量而将其锁定时,得到该互斥信号量的所有权。相反当一个任务释放信号量时,失去对其所有权。
递归访问指的是一个任务中被多个调用函数Routine对同一共享资源的访问。一个递归的互斥信号量允许嵌套锁定互斥信号量,而不引起死锁,每个获取信号量的调用必须与释放信号量的调用相匹配,用于同步的信号量不支持嵌套访问,否则会被永久阻塞。
删除安全指在一个受信号量保护的临界区,经常需要保护在临界区执行的任务不会被意外的删除。删除一个在临界区执行的任务可能会引起意想不到的后果,造成信号量不可用或者资源破坏。解决方法是提供“任务保护”和“解除任务保护”原语对。
以下是四种互斥机制的对比:
(2)二值信号量:用于解决同步问题。主要用于任务与任务之间双向同步、任务与中断服务程序之间的同步。二值信号量初始值为0,表示同步事件还没有产生。当任务申请二值信号量的时候Pend表示需要等待某一个同步事件的发生(阻塞)。从0改变为1表示同步事件的发生Post,等待的任务就会被唤醒。
示例:假设task2优先级高于task1,sem1和sem2初始值为0,使用二值信号量实现任务间双向同步,信号量的申请和释放是在两个任务中进行的。
(3)计数信号量:用于解决资源计数问题。计数信号量用于控制系统中共享资源的多个实例的使用,允许多个任务同时访问同一种资源的多个实例。计数信号量被初始化为一个非负整数n,即该种共享资源的数目。成功获取资源后信号量会减一,直到变为0。
示例:解决有界缓冲问题,在系统中有一个缓冲区,若干个缓冲单元,存在生产者任务和消费者任务,前者生产数据,后者消费数据
具体实现如下所示:
1.3信号量的具体实现
(1)实现原理
信号量的数据结构包括信号量控制块、信号量名字ID,任务等待列表。信号量控制块管理所有创建的信号量,内核在系统运行时动态分配和回收信号量控制块。信号量的类型不同,它的控制块也有所不同。
uCOS-II采用通用的数据结构——事件控制块ECB作为同步和通信机制的基本数据结构 ,事件类型包括管理信号量、管理事件、消息队列。
当一个事件发生后,等待事件列表中优先级最高的任务(即在OSEventTbl[]和OSEventGr