125
电电电电电电电电电电电电电电电 电电电电 电电电

嵌入式系统及应用

  • Upload
    nuwa

  • View
    74

  • Download
    0

Embed Size (px)

DESCRIPTION

嵌入式系统及应用. 第六章 同步、互斥与通信. 主要内容. 概述 信号量 邮箱和消息队列 事件 异步信号* 管道*. 概述. 多任务系统中任务之间的关系 相互独立 仅竞争 CPU 资源 竞争除 CPU 外的其他资源(互斥) 同步 协调彼此运行的步调,保证协同运行的各个任务具有正确的执行次序 通信 彼此间传递数据或信息,以协同完成某项工作. 概述. 任务能以以下方式与中断处理程序或其他任务进行同步或通信: 单向同步或通信 :一个任务与另一个任务或一个 ISR 同步或通信。 - PowerPoint PPT Presentation

Citation preview

Page 1: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

嵌入式系统及应用

Page 2: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

第六章

同步、互斥与通信

Page 3: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

主要内容

•概述•信号量•邮箱和消息队列•事件•异步信号 *•管道 *

Page 4: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

概述

•多任务系统中任务之间的关系– 相互独立 仅竞争 CPU 资源– 竞争除 CPU 外的其他资源(互斥)– 同步 协调彼此运行的步调,保证协同运行的各

个任务具有正确的执行次序 – 通信 彼此间传递数据或信息,以协同完成某项

工作

Page 5: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•任务能以以下方式与中断处理程序或其他任务进行同步或通信:– 单向同步或通信:一个任务与另一个任务或

一个 ISR 同步或通信。 – 双向同步或通信:两个任务相互同步或通信。

双向同步不能在任务与 ISR 之间进行,因为ISR 不能等待。

概述

Page 6: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

ISR xISR x Task yTask y

POST PEND 任务与任务与 ISRISR之间的同步之间的同步(单向)(单向)

Task xTask x Task yTask y

POST PEND

POSTPEND

任务与任务任务与任务之间的同步之间的同步(双向)(双向)

任务与任务任务与任务之间的同步之间的同步(单向)(单向)

Task xTask x Task yTask y

POST PEND

Page 7: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•在嵌入式多任务系统中,任务间的耦合程度是不一样的:– 耦合程度较高:任务之间需要进行大量的通

信,相应的系统开销较大;– 耦合程度较低:任务之间不存在通信需求,

其间的同步关系很弱甚至不需要同步或互斥,系统开销较小。

•研究任务间耦合程度的高低对于合理地设计应用系统、划分任务有很重要的作用。

概述

Page 8: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•在单处理器平台上,嵌入式操作系统内核提供的同步、互斥与通信机制主要包括:– 信号量( semaphore ),用于互斥与同步– 事件(组)( event group ),用于同步– 异步信号( asynchronous signal ),用于

同步– 邮箱( mailbox )、消息队列( message q

ueue ),用于消息通信– 管道( pipe ),提供非结构化数据交换和

实现同步

概述

Page 9: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•以下一些机制也可用于同步与通信(在单处理器或多处理器系统中):– 全局变量– 共享内存– Sockets

– 远程过程调用( Remote Procedure Call )

概述

Page 10: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

第一节

信号量信号量的种类及用途互斥信号量二值信号量计数信号量信号量机制的主要数据结构典型的信号量操作

Page 11: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•信号量用于实现任务与任务之间、任务与中断处理程序之间的同步与互斥。

•信号量一般分为三种:

信号量的种类及用途

用于解决互斥问题。它比较特殊,可能会引起优先级反转问题。

用于解决同步问题

用于解决资源计数问题

将信号量进行种类细分,可以根据其用途,在具体实现时做专门处理,提高执行效率和可靠性。

Page 12: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

• 用互斥信号量保护的代码区称作“临界区”,临界区代码通常用于对共享资源的访问。

• 互斥信号量的值被初始化成 1,表明目前没有任务进入“临界区”,但最多只有一个任务可以进入“临界区”。

• 第一个试图进入“临界区”的任务将成功获得互斥信号量,而随后试图进入用同一信号量保护的临界区的所有其他任务就必须等待。

• 当任务离开“临界区”时,它将释放信号量并允许正在等待该信号量的任务进入“临界区”。

互斥信号量

Task1

Task2

共享资源

Page 13: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

互斥信号量

• 共享资源可能是一段存储器空间、一个数据结构或 I/O 设备,也可能是被两个或多个并发任务共享的任何内容。

• 使用互斥信号量可以实现对共享资源的串行访问,保证只有成功地获取互斥信号量的任务才能够释放它。

• 互斥信号量是一种特殊的二值信号量,一般它支持所有权、递归访问、任务删除安全和一些避免优先级反转、饥饿、死锁等互斥所固有问题的协议。

Page 14: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

互斥信号量状态图

互斥信号量状态图

开启 锁定初始化值为 1

申请并获得值为 0

释放值为 1

申请 ( 递归 ) 并获得锁定数加 1

释放 (递归 )锁定数减 1

Page 15: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

互斥信号量•所有权:当一个任务通过获取互斥信号量而将其锁定时,得到该互斥信号量的所有权。相反,当一个任务释放信号量时,失去对其的所有权。

•当一个任务拥有互斥信号量时,其他的任务不能再锁定或释放它,即任务要释放互斥信号量,必须事前先获取该信号量。

Page 16: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

Task1

RoutineA

RoutineB

互斥信号量•嵌套(递归)资源访问

– 如果 Task1 调用 RoutineA ,而 RoutineA 又调用 RoutineB ,并且三者访问相同的共享资源,就发生了递归共享资源的访问同步问题。

共享资源

一个递归的互斥信号量允许嵌套锁定互斥信号量,而不引起死锁。

Page 17: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

互斥信号量•嵌套(递归)资源访问

– 每个获取信号量的调用必须与释放信号量的调用相匹配。当最外层的获取信号量的调用与释放信号量的调用匹配时,该信号量才允许被其它任务访问。

– 用于同步的信号量不支持嵌套访问,任务如果对同步信号量使用上述操作是错误的,任务会被永久阻塞,并且阻塞条件永远不会解除。

Page 18: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

互斥信号量•删除安全:

– 在一个受信号量保护的临界区,经常需要保护在临界区执行的任务不会被意外地删除。

– 删除一个在临界区执行的任务可能引起意想不到的后果,造成保护资源的信号量不可用,可能导致资源处于破坏状态,也就导致了其它所有要访问该资源的任务无法得到满足。

Page 19: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

互斥信号量•删除安全:

– 为避免任务在临界区执行时不被意外删除:• 提供“任务保护”和“解除任务保护”原语对• 同时,为互斥信号量提供“删除安全”选项。在创

建信号量的时候使用这个选项,当应用每次获取信号量时隐含地使能“任务保护”功能,当每次释放信号量时隐含地使用“解除任务保护”功能。

Page 20: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

二值信号量• 二值信号量主要用于任务与任务之间、任务与中断服务程序之间的同步– 用于同步的二值信号量初始值为 0 ,表示同步事件尚

未产生;– 任务申请信号量以等待该同步事件的发生;– 另一个任务或 ISR 到达同步点时,释放信号量(将其

值设置为 1 )表示同步事件已发生,以唤醒等待的任务。

Task1 Task2

二值信号量初值为 0

Page 21: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

二值信号量

二值信号量状态图

可获得 不可获得

申请并获得(值为 0)

释放(值为 1)

初始化值为 0

Page 22: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

Task1(){

…… 执行一些操作 ; 将信号量 sem1 置1;

申请信号量 sem2; …… ……}

Task2(){ …… 申请信号量 sem1;

执行一些操作 ; 将信号量 sem2 置1; …… ……

}

Task2 申请信号量 sem1 失败,系统切换到 Task1

sem1 被置 1 后, Task2 得到 sem1 并抢占 Task1

Task2 运行到某处时因某种原因被阻塞,系统切换到 Task1

用二值信号量实现两个任务之间的双向同步用二值信号量实现两个任务之间的双向同步•Task2Task2 优先级高于优先级高于 Task1Task1•sem1sem1 和和 sem2sem2 的初始值均为的初始值均为 00

Page 23: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

计数信号量 计数信号量用于控制系统中共享资源的多个实例的使用,允许多个任务同时访问同一种资源的多个实例

计数信号量被初始化为 n (非负整数),n 为该种共享资源的数目。

Task1

Task2

共享资源实例 n

Task m

共享资源实例1

……

……

Page 24: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

计数信号量

计数信号量状态图

可获得 不可获得初始化值大于 0

申请并获得值为 0

释放值为 1

申请并获得值减 1

释放值加 1

Page 25: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量机制的主要数据结构

SCB1

SCB2

……

……

信号量控制块

count

信号量名字或 ID

Task1 Task2 ……

任务等待列表

Page 26: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量机制的主要数据结构• 信号量控制块:管理所有创建的信号量,内核在系统运行时动态分配和回收信号量控制块• 互斥和二值信号量控制块结构: Binary_Semaphore_Control_Block

wait_queue 任务等待队列attributes 信号量属性

lock_nesting_behavior 试图嵌套获得时的规则 wait_discipline 任务等待信号量的方式

priority_ceiling 优先级天花板值lock 是否被占有holder 拥有者 nest_count 嵌套层数

Page 27: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•计数信号量控制结构 Counting_Semaphore_Control_Block

wait_queue 任务等待队列 attributes 计数信号量属性 maximum_count 最大计数值 wait_discipline 任务等待信号量的方式 count 当前计数值

信号量机制的主要数据结构

Page 28: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量内部实现机制实例说明- µC/OS-II

• 事件控制块 ECB -同步与通信机制的基本数据结构

typedef struct{INT8U OSEventType;// 事件类型INT8U OSEventGrp;// 等待任务所在的组INT16U OSEventCnt;// 计数器(信号量)void *OSEventPtr;//指向消息或消息队列的指针INT8U OSEventTbl[OS_EVENT_TBL_SIZE];// 等待任

务列表}OS_EVENT;

Page 29: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量内部实现机制实例说明- µC/OS-II

• 当一个事件发生后,等待事件列表中优先级最高的任务(即在 .OSEventTbl[]&OSEventGrp中所有被置 1的位中优先级数值最小的任务)得到该事件。

Page 30: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量内部实现机制实例说明- µC/OS-II

• 当 .OSEventTbl[n]中的任何一位为 1时, OSEventGrp中的第 n 位为1。

与任务就绪列表类似!

Page 31: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量内部实现机制实例说明- µC/OS-II

• 将一个任务插入到等待事件的任务列表中:

pevent->OSEventGrp |= OSMapTbl[prio >> 3];

pevent->OSEventTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

与将一个任务插入到就绪列表中的操作类似!

Index Bit mask (Binary)

0 0 0 0 0 0 0 0 11 0 0 0 0 0 0 1 02 0 0 0 0 0 1 0 0

3 0 0 0 0 1 0 0 0

4 0 0 0 1 0 0 0 0

5 0 0 1 0 0 0 0 0

6 0 1 0 0 0 0 0 0

7 1 0 0 0 0 0 0 0

Page 32: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量内部实现机制实例说明- µC/OS-II

•从等待事件的任务列表中使任务脱离等待状态if ((pevent->OSEventTbl[prio >> 3] &= ~OSMapTbl[prio

& 0x07]) == 0) {

pevent->OSEventGrp &= ~OSMapTbl[prio >> 3];

}

与将任务从就绪列表中清除的操作类似!

Page 33: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量内部实现机制实例说明- µC/OS-II

•在等待事件的任务列表中查找优先级最高的任务y = OSUnMapTbl[pevent->OSEventGrp];

x = OSUnMapTbl[pevent->OSEventTbl[y]];

prio = (y << 3) + x;

与查找优先级最高的就绪任务的操作类似!

Page 34: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

信号量内部实现机制实例说明- µC/OS-II

•空闲事件控制块链表

Page 35: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的信号量操作

•创建信号量•获取(申请)信号量•释放信号量•删除信号量•清除信号量的任务等待列表 •获取有关信号量的各种信息

Page 36: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

创建信号量

• 功能:根据应用传递的参数创建一个信号量• 参数:信号量的名字、属性和初始值等。• 内核动作:

–从空闲信号量控制块链中分配一个信号量控制块,并初始化信号量属性。

– 创建成功时,为其分配唯一的 ID 号返回给应用。– 如果已创建信号量数量已达到用户配置的最大

数量,就返回错误。

Page 37: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

创建信号量

信号量的属性包括:•类型•任务等待信号量的方式(即排列的顺序)•与任务删除安全、递归访问以及解决优先级反转的策略相关的参数(只针对互斥信号量)。

Page 38: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

创建信号量

信号量的属性

信号量的类型互斥信号量(MUTEX_SEMAPHORE)

计数信号量( COUNTING_SEMAPHORE)

二值信号量( BINARY_SEMAPHORE)

任务等待信号量的方式

先进先出( FIFO)顺序

优先级( PRIORITY)顺序

优先级反转问题的解决方法(只适用于互斥信号量)

优先级继承算法( INHERIT_PRIORITY)

优先级天花板算法 (PRIORITY_CEILING) ,需给出所有可能获得此信号量的任务中优先级最高的任务的优先级。

Page 39: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

创建一个信号量 OSSemCreate()OS_EVENT *OSSemCreate (INT16U cnt){

OS_EVENT *pevent;pevent = OSEventFreeList;//从空闲事件控制块链中取得一个 ECBif (OSEventFreeList != (OS_EVENT *)0) { OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;}if (pevent != (OS_EVENT *)0) { //初始化 ECB的各个域

pevent->OSEventType = OS_EVENT_TYPE_SEM; //事件类型为信号量pevent->OSEventCnt = cnt; //信号量的初始计数值pevent->OSEventPtr = (void *)0;OS_EventWaitListInit(pevent); //初始化等待任务列表

}return (pevent); //调用者需检查返回值,如果为 NULL则表示建立失败

}

Page 40: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

获取(申请)信号量•功能:试图获得应用指定的信号量。

if 信号量的值大于 0

then 将信号量的值减 1

else 根据接收信号量的选项,将任务放到等待队列中,或是直接返回

Page 41: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

获取(申请)信号量

•当所申请的信号量不能被立即获得时,可以有以下几种选择:– 永远等待 – 不等待,立即返回,并返回一个错误状态码–指定等待时限(可有效避免死锁)注意:– 不允许在 ISR中选择等待– 当任务选择等待时,将被按 FIFO 或优先级顺序

放置在等待队列中

Page 42: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

获取(申请)信号量• 如果任务等待一个使用优先级继承算法的互斥信号量,且它的优先级高于当前正占有此信号量的任务的优先级,那么占有信号量的任务将继承这个被阻塞的任务的优先级。

• 如果任务成功地获得一个采用优先级天花板算法的互斥信号量,它的优先级又低于优先级天花板,那么它的优先级将被抬升至天花板。

Page 43: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

获取(等待)一个信号量 OSSemPend()void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err){

if (pevent->OSEventCnt > 0) { //信号量值大于 0,成功获得信号量并返回pevent->OSEventCnt--; *err = OS_NO_ERR;return;} OSTCBCur->OSTCBStat |= OS_STAT_SEM; //设置任务状态为等待信号量OSTCBCur->OSTCBDly = timeout; //设置等待时限OS_EventTaskWait(pevent);//将任务放置到信号量的等待列表中 OS_Sched(); //内核实施任务调度,系统切换到另一就绪任务执行if (OSTCBCur->OSTCBStat & OS_STAT_SEM) { //判断任务恢复执行的原因,如果等待时限超时但仍然未获得信号量,则返回超时信息OSEventTO(pevent); *err = OS_TIMEOUT;return;}OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; *err = OS_NO_ERR; //任务由于获得信号量而恢复执行,本调用成功返回

}

Page 44: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

获取(无等待地请求)一个信号量 OSSemAccept()

INT16U OSSemAccept (OS_EVENT *pevent){

INT16U cnt;cnt = pevent->OSEventCnt; if (cnt > 0) {

pevent->OSEventCnt--; }return (cnt);

}注意:即使不能成功获得信号量(返回值为 0),调用者也不会被阻塞。此函数可以在中断处理程序中使用。

Page 45: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

释放信号量

•功能:释放一个应用指定的信号量。 if 没有任务等待这个信号量then 信号量的值加 1

else 将信号量分配给一个等待任务(将相应的任务移出等待队列,使其就绪)

•如果使用了优先级继承或优先级天花板算法,那么执行该功能(系统调用)的任务的优先级将恢复到原来的高度。

Page 46: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

释放一个信号量 OSSemPost()INT8U OSSemPost (OS_EVENT *pevent){

if (pevent->OSEventGrp!=0x00) { //如果有任务在等待该信号量OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM); // 使等

待任务列表中优先级最高的任务就绪OS_Sched(); // 内核实施任务调度return (OS_NO_ERR);// 成功返回

} if (pevent->OSEventCnt < 65535) {//如果没有任务等待该信号量,并且信号量的值未溢出

pevent->OSEventCnt++; // 信号量的值加 1return (OS_NO_ERR);// 成功返回

} return (OS_SEM_OVF);// 信号量溢出

}

Page 47: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除信号量

•功能:从系统中删除应用指定的一个信号量

•内核动作:将信号量控制块返还给系统•删除信号量的不一定是创建信号量的任务•如果有任务正在等待获得该信号量,执行此功能将使所有等待这个信号量的任务回到就绪队列中,且返回一个状态码指示该信号量已被删除

Page 48: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除信号量•企图获取已删除的信号量将返回一个错误;•在互斥信号量正被使用时(已经被某任务获取),不能删除它。因为该信号量正在保护一个共享资源或临界代码段,该动作可能造成数据崩溃或其他严重问题。

Page 49: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除一个信号量 OSSemDel()OS_EVENT *OSSemDel(OS_EVENT *pevent, INT8U opt, INT8U *err){

BOOLEAN tasks_waiting;if(pevent->OSEventGrp!=0x00{//根据是否有任务在等待信号量设置等待标志tasks_waiting=TRUE;}else{tasks_waiting=FALSE;}switch(opt){case OS_DEL_NO_PEND://如果有任务等待信号量则不删除信号量if(task_waiting==FALSE{//没有任务等待,释放 ECB回空闲链pevent->OSEventType=OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr=OSEventFreeList; OSEventFreeList=pevent;//调整空闲ECB链头指针*err=OS_NO_ERR;return((OS_EVENT)0);}else{ *err=OS_ERR_TASK_WAITING;//有任务等待,删除信号量失败return(pevent);}

Page 50: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除一个信号量 OSSemDel()case OS_DEL_ALWAYS://无论有无任务等待都删除信号量

// 将等待列表中的每个任务都设置成就绪while(pevent->OSEventGrp!=0x00){OS_EventTaskRdy(pevent,(void *)0, OS_STAT_SE

M);}// 释放该信号量的 ECB 回空闲控制块链pevent->OSEventType=OS_EVENT_TYPE_UNUSED;pevent->OSEventFreeList; OSEventFreeList=pevent;//如果之前有任务等待信号量,内核实施任务调度if(tasks_waiting==TRUE){OS_Sched();}*err=OS_NO_ERR;return((OS_EVENT *)0);

default:*err=OS_ERR_INVALID_OPT;return(pevent);

}}

Page 51: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

清除信号量的任务等待列表

•为了清除等待一个信号量的所有任务,某些内核支持 Flush操作,以便释放信号量等待任务列表中的所有任务。当多个任务的执行必须在某些点相遇时,需要这样的机制。

SignalTask Task2

二值信号量初值为 0

Flush

Task1

Task3

Page 52: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

第二节

邮箱和消息队列通信方式概述消息队列机制的主要数据结构典型的消息队列操作消息队列的其他典型使用

Page 53: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•任务间的通信方式–直接通信。在通信过程中双方必须明确地知

道(命名)彼此:• Send (P , message) – 发送一个消息到任务 P

• Receive(Q , message) – 从任务 Q接收一个消息

– 间接通信。通信双方不需要指出消息的来源或去向,而通过中间机制来通信。如:

• send(A , message) – 发送一个消息给邮箱 A• receive(A , message) – 从邮箱 A接收一个消

通信方式概述

Page 54: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

• 消息队列:属于间接通信方式• 消息:内存空间中一段长度可变的缓冲区,其长度和内容均可以由用户定义,其内容可以是实际的数据、数据块的指针或空。

• 对消息内容的解释由应用完成。– 从操作系统观点看,消息没有定义的格式,所有的

消息都是字节流,没有特定的含义。– 从应用观点看,根据应用定义的消息格式,消息被

解释成特定的含义。– 应用可以只把消息当成一个标志,这时消息机制用

于实现同步

概述

Page 55: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

• 一些操作系统内核把消息进一步分为:邮箱和消息队列– 邮箱仅能存放单条消息,它提供了一种低开销的机制来传送信息。每个邮箱可以保存一条大小为若干个字节的消息。

– 消息队列可存放若干消息,提供了一种任务间缓冲通信的方法。

• 消息机制可支持定长与可变长度两种模式的消息,可变长度的消息队列需要对队列中的每一条消息增加额外的存储开销。

概述

Page 56: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

消息队列机制的主要数据结构队列控制块

队列长度

QCB1

队列名或 ID

Task3 Task4 ……

接收任务等待列表

Task1 Task2……

发送任务等待列表 最大

消息长度

QCB2……

消息队列及其相关的参数和支持数据结构

Page 57: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

消息队列状态图

非空 满

队列创建消息数为 0

消息队列状态图

消息发送消息数加 1

消息发送消息数为 1

消息接收消息数为 0

消息接收消息数减 1

消息接收消息数减1

消息发送消息数等于队列长度

Page 58: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

消息队列机制的主要数据结构

• 消息队列控制块– 管理所有创建的消息队列,系统运行时动态分配和回收消息队列控制块

• 消息队列缓冲区– 存放发送到该队列的消息,接收者从缓冲区中取出消

息。– 消息的发送或接收有两种方法(影响消息缓冲区结

构):• 将数据从发送任务的空间完全拷贝到接收任务的空间中(效率

较低,执行时间与消息大小有关)• 只传递指向数据存储空间的指针(提高系统性能)

Page 59: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

Sending Task Receiving Task

Message1

Message1

Message1

发送任务的内存区域

消息队列的内存区域

接收任务的内存区域

1st copy 2nd copy

发送和接收消息的消息拷贝和内存使用发送和接收消息的消息拷贝和内存使用•这种消息传递方法效率低、占用空间大这种消息传递方法效率低、占用空间大•一种效率更高的方式是传递消息指针一种效率更高的方式是传递消息指针

Page 60: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

number_of_message

max_message_countnumber_of_messagemax_message_size

wait_discipline

wait_queue

queue_startqueue_in

queue_outqueue_end

message

message

message

message

message

message

message

message

message

max_message_count

消息队列控制块 消息队列

缓冲区

消息队列机制的主要数据结构

Page 61: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心消息队列的环形缓冲消息队列的环形缓冲

消息队列机制的主要数据结构

max_message_count

queue_endqueue_start

queue_out

number_of_message queue_in

消息指针

Page 62: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的消息队列操作

•创建消息队列•发送普通消息•发送紧急消息•发送广播消息•接收消息•删除消息队列•获取有关消息队列的各种信息

Page 63: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

创建消息队列

•创建消息队列时,调用者可以指定如下参数:– 消息的最大长度– 每个消息队列中最多的消息数– 消息队列的属性

• 任务等待消息时的排队方式: FIFO 或 PRIORITY

•系统为新创建的消息队列分配唯一的 ID

Page 64: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

发送消息•根据紧急程度的不同,消息通常可分为普通消息与紧急消息。– 如果有任务正在等待消息(即消息队列为空),则普通消息发送和紧急消息发送的执行效果是一样的。任务从等待队列移到就绪队列中,消息被拷贝到任务提供的缓冲区中(或者由接收任务得到指向消息的指针)。

– 如果没有任务等待,发送普通消息将消息放在队列尾,而发送紧急消息将消息放在队列头。

Page 65: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

发送消息

Msg 3

接收任务等待列表

Msg 2 Msg 1

消息队列

发送普通消息-先进先出( FIFO)次序

Msg 3

接收任务等待列表

Msg 2Msg 1

消息队列

发送紧急消息-后进先出( LIFO)次序

Page 66: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

发送消息• 如果发送消息时队列已被填满,则不同的操作系统可能采取不同的处理办法:– 挂起试图向已满的消息队列中发送消息的任务(不适用于中断服务程序)

– 简单地丢弃该条消息并向调用者返回错误信息• 广播消息。在此之前所有试图从队列中接收消息的任务此时都将获得相同的消息。该功能拷贝消息到各任务的消息缓冲中(或者让所有的等待任务得到指向消息的指针),并唤醒所有的等待任务。

Page 67: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收消息•如果指定的消息队列中有消息,则将其中的第一条消息拷贝到调用者的缓冲区(或者将第一条消息指针传递给调用者),并从消息队列中删除它。

•如果此时消息队列中没有消息,则可能出现以下几种情况:– 永远等待消息的到达:等待消息的任务按 FI

FO 或优先级高低顺序排列在等待队列中 – 等待消息且指定等待时限:等待消息的任务按 FIFO 或优先级高低顺序排列在等待队列中

– 不等待,强制立即返回

Page 68: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收消息

• 限时等待可有效预防死锁• 中断服务程序接收消息时必须选择不等待,因为中断服务程序是不能被阻塞的。

• 如果消息队列被应用删除,则所有等待该消息队列的任务都被返回一个错误信息,并回复到就绪状态。

Page 69: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收消息

Task 4High

消息队列接收任务等待列表

任务等待列表-基于优先级的次序

Task 2medium

Task 3medium

Task 1Low

Task 4High

消息队列接收任务等待列表

任务等待列表-先进先出( FIFO)次序

Task 2medium

Task 3medium

Task 1Low

Page 70: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除消息队列

• 从系统中删除指定的消息队列,释放消息队列控制块及消息队列缓冲区。

• 任何知道此消息队列 ID号的代码都可以删除它。• 消息队列被删除后,所有等待从这个消息队列接收消息的任务都回到就绪态,并得到一个错误信息表明消息队列已被删除。

Page 71: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

消息队列的其他典型使用

•紧耦合的单向数据通信:发送任务发送消息后要求一个响应信号,表明接收任务已经成功接收到消息。

Task1 Task2

Page 72: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

消息队列的其他典型使用

•紧耦合的双向数据通信 :如果数据需要在任务之间双向流动,则可以采用紧耦合的双向数据通信模式(也称为全双工通信)。

Task1Task2

Page 73: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

第三节

事 件概述事件机制的主要数据结构典型的事件操作事件机制的典型应用

Page 74: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

• 在嵌入式实时内核中,事件是指一种表明预先定义的系统事件已经发生的机制。

• 事件机制用于任务与任务之间、任务与 ISR之间的同步。其主要的特点是可实现一对多的同步。

• 一个事件就是一个标志,不具备其它信息。• 一个或多个事件构成一个事件集。事件集可以用一个指定长度的变量(比如一个 8bit, 16bit或 32bit的无符号整型变量,不同的操作系统其具体实现不一样)来表示,而每个事件由在事件集变量中的某一位来代表。

概述

Page 75: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

• 事件及事件集有以下特点: – 事件间相互独立– 事件仅用于同步,不提供数据传输功能– 事件无队列,即多次发送同一事件,在未经过任何

处理的情况下,其效果等同于只发送一次。• 提供事件机制的意义在于:

– 当某任务要与多个任务或中断服务同步时,就需要使用事件机制。

– 若任务需要与一组事件中的任意一个发生同步,可称为独立型同步(逻辑“或”关系)。

– 任务也可以等待若干事件都发生时才同步,称为关联型同步(逻辑“与”关系)。

概述

Page 76: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

““ 或”同步和“与”同步或”同步和“与”同步

概述

任务

任务

任务

任务

ISR

ISR

OR

AND

“与”型同步

“或”型同步

事件集

事件集

POST

POST

PEND

PEND

Page 77: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

用多个事件的组合发信号给多个任务用多个事件的组合发信号给多个任务

概述

任务

任务

任务

ISR

OR

AND

事件集

事件集

事件集( 8, 16或 32位)

POST

PEND

PEND

Page 78: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

•术语:– 发送事件集 。指在一次发送过程中发往接收

者(比如任务)的一个或多个事件的组合。 – 待处理事件集。指已被发送到一个接收者但还没有被接收(即正在等待处理)的所有事件的集合。

– 事件条件。指事件接收者在一次接收过程中期待接收的一个或多个事件的集合。

• “ 或”同步:待处理事件集只要包括事件条件中的任一事件即可满足要求;

• “ 与”同步:其二是待处理事件集必须包括事件条件中的全部事件方可满足要求。

概述

Page 79: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

事件机制的主要数据结构

•事件集控制块:管理所有创建的事件集或者•事件集附属于任务,不需创建,其相关参数成为任务控制块的一部分

Page 80: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

事件的内部实现机制实例说明- µC/OS-II

• 事件标志组数据结构typedef struct{

INT8U OSFlagType;//指示本数据结构的类型void *OSFlagWaitList;// 等待事件标志的任务链表OS_FLAGS OSFlagFlags;//各事件标志的当前状态

}OS_FLAG_GRP;• 事件标志节点数据结构typedef struct{

void *OSFlagNodeNext;// 后驱指针void *OSFlagNodePrev;// 前驱指针void *OSFlagNodeTCB;// 任务控制块指针void *OSFlagNodeFlagGrp;//指回 OS_FLAG_GRP结构OS_FLAGS OSFlagNodeFlags;// 所等待的事件标志组合INT8U OSFlagNodeWaitType;// 等待类型(与、或)

}OS_FLAG_NODE;

Page 81: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

事件标志组、事件标志节点及任务控制块之间的关系

OS_FLAG_GRP OS_FLAG_NODE

.OSTCBFlagNode

.OSFlagNodeFlags

.OSFlagNodeWaitType

.OSFlagNodeNext

.OSFlagNodePrev

.OSFlagNodeTCB

.OSFlagWaitList

.OSFlagFlags

.OSFlagType

AND or OR AND or OR AND or OROS_EVENT_TYPE_FLAG

00

.OSTCBFlagNode

OS_TCB

Page 82: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的事件操作

•创建事件集•删除事件集•发送事件(集)•接收事件(集)•获取有关事件集的各种信息

Page 83: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

创建事件集•申请空闲事件集控制块,设置事件集属性,初始化控制块中的域,分配 ID号

Page 84: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

创建一个事件标志组 OSFlagCreate()OS_FLAG_GRP *OSFlagCreate(OS_FLAGS flags, INT8U *err){

OS_FLAG_GRP *pgrp;pgrp=OSFlagFreeList;// 获取一个空闲事件标志组结构if(pgrp!=(OS_FLAG_GRP *)0){// 获取成功,初始化该结构中的域

OSFlagFreeList=(OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList;//调整空闲结构链头指针

pgrp->OSFlagType=OS_EVENT_TYPE_FLAG;pgrp->OSFlagFlags=flags;// 初始化当前各事件标志的状态pgrp->OSFlagWaitList=(void *)0;//尚无任务等待事件标

志*err=OS_NO_ERR;

}else{*err=OS_FLAG_GRP_DEPLETED;}return(pgrp);

}

Page 85: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收事件(集)在接收事件(集)时可以有如下选项

WAIT

NO_WAIT

接收事件(集)时可等待

接收事件(集)时不等待

•接收者永远等待,直到事件条件被满足后成功返回; •接收者根据指定的时限等待。

EVENT_ALL

EVENT_ANY

待处理事件集必须包含事件条件中的全部事件方可满足要求,即按照“与”条件接收事件

待处理事件集只要包含事件条件中的任一事件即可满足要求,即按照“或”条件接收事件

Page 86: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收(等待)事件标志组的事件标志位 OSFlagPend()

OS_FLAGS OSFlagPend(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *err)

{OS_FLAG_NODE node;// OS_FLAG_NODE作为局部变量存在于调用该函数的任务堆栈中OS_FLAGS flags_cur;OS_FLAGS flags_rdy;switch(wait_type){

case OS_FLAG_WAIT_SET_ALL:// 任务以“与”方式等待事件标志flags_rdy=pgrp->OSFlagFlags&flags;if(flags_rdy==flags){// 事件标志当前状态与等待条件相符

pgrp->OSFlagFlags&=~flags_rdy;//清除(即“消费”)满足条件的事件标志

flags_cur=pgrp->OSFlagFlags;*err=OS_NO_ERR;return(flags_cur);//返回处理后的事件标志组

}else{OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);}

// 事件标志当前状态与等待条件不相符,任务被阻塞break;

Page 87: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收(等待)事件标志组的事件标志位 OSFlagPend()

case OS_FLAG_WAIT_SET_ANY: // 任务以“或”方式等待事件标志 flags_rdy=pgrp->OSFlagFlags&flags;if(flags_rdy!=(OS_FLAGS)0){// 有满足条件的事件标志

pgrp->OSFlagFlags&=~flags_rdy; //清除(即“消费”)满足条件的事件标志

flags_cur=pgrp->OSFlagFlags; *err=OS_NO_ERR; return(flags_cur); //返回处理后的事件标志组

}else{OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);}

// 事件标志当前状态与等待条件不相符,任务被阻塞break;

default:flags_cur=(OS_FLAGS)0;*err=OS_FLAG_ERR_WAIT_TYPE;return(flags_cur);

}

Page 88: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

OS_Sched();// 当前任务被放到事件标志等待链后,内核实施任务调度if(OSTCBCur->OSTCBStat & OS_STAT_FLAG){//判断任务重新就绪的原因,如果是等待超时

OS_FlagUnlink(&node);// 将任务从事件标志等待链中解除下来OSTCBCur->OSTCBStat=OS_STAT_RDY;// 设置当前任务状态为就绪flags_cur=(OS_FLAGS)0;//无效的事件标志状态*err=OS_TIMEOUT;//超时信号

}else{// 任务重新就绪的原因是在限定时间得到了满足条件的事件标志pgrp->OSFlagFlags&=~OSTCBCur->OSTCBFlagsRdy; //清除(即“消

费”)满足条件的事件标志flags_cur=pgrp->OSFlagFlags;*err=OS_NO_ERR;

}return(flags_cur);

}

接收(等待)事件标志组的事件标志位 OSFlagPend()

Page 89: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

添加一个任务到事件标志组等待任务链表中OS_FlagBlock()

OS_FLAG_GRP

OS_EVENT_TYPE_FLAG AND or OR AND or OR

0

0

OS_TCB

OS_TCBOSTCBCur

AND or OR

OS_FLAG_NODE

OS_FLAG_NODE

0

Page 90: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收(无等待地获取)事件标志 OSFlagAccept()

OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT8U *err)

{OS_FLAGS flags_cur, flags_rdy;*err = OS_NO_ERR;switch (wait_type) {//判断等待事件标志的方式

case OS_FLAG_WAIT_SET_ALL://”与”方式等待flags_rdy = pgrp->OSFlagFlags & flags;if (flags_rdy == flags) pgrp->OSFlagFlags &= ~flags

_rdy;// 事件标志当前状态与等待条件相符,清除(即“消费”)相应的事件标志

else *err = OS_FLAG_ERR_NOT_RDY;// 不符合条件,返回错误信息

flags_cur = pgrp->OSFlagFlags;break;

Page 91: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

接收(无等待地获取)事件标志 OSFlagAccept()

case OS_FLAG_WAIT_SET_ANY://”或”方式等待flags_rdy = pgrp->OSFlagFlags & flags;if (flags_rdy != (OS_FLAGS)0)

pgrp->OSFlagFlags &= ~flags_rdy;// 事件标志当前状态与等待条件相符,清除(即“消费”)相应的事件标志

else *err = OS_FLAG_ERR_NOT_RDY; // 不符合条件,返回错误信息

flags_cur = pgrp->OSFlagFlags;break;

default:flags_cur = (OS_FLAGS)0;//0表示无效的事件标志组*err = OS_FLAG_ERR_WAIT_TYPE;//错误的等待类型break;

} return (flags_cur);}

Page 92: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

发送事件(集)•调用者(任务或中断)构造一个事件(集),将其发往接收者(比如目标任务)。可能会出现以下几种情况之一:–目标任务正在等待的事件条件得到满足,任务

就绪;–目标任务正在等待的事件条件没有得到满足,

该事件(集)被按“或”操作,保存到目标任务的待处理事件集中,目标任务继续等待;

–目标任务未等待事件(集),该事件(集)被按“或”操作,保存到目标任务的待处理事件集中。

Page 93: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

发送(置位)事件标志组中的事件标志 OSFlagPost()

OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U *err){

OS_FLAG_NODE *pnode;BOOLEAN sched= FALSE;// 初始化调度标志OS_FLAGS flags_cur, flags_rdy;

pgrp->OSFlagFlags |= flags;// 置位事件标志pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;// 获取任务等待链头节点while (pnode != (OS_FLAG_NODE *)0) {//如果有任务等待,遍历等待链

switch (pnode->OSFlagNodeWaitType) { case OS_FLAG_WAIT_SET_ALL://”与”方式等待

flags_rdy = pgrp->OSFlagFlags & pnode->OSFlagNodeFlags; if (flags_rdy == pnode->OSFlagNodeFlags) {//符合等待条

件 if (OS_FlagTaskRdy(pnode, flags_rdy) == TR

UE) sched = TRUE;//如果任务就绪,设置调度标志

} break;

Page 94: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

case OS_FLAG_WAIT_SET_ANY://”或”方式等待 flags_rdy = pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;

if (flags_rdy != (OS_FLAGS)0) {// 有满足条件的事件标志

if (OS_FlagTaskRdy(pnode, flags_rdy) == TRUE) sched = TRUE; //如果任务就绪,设置调度标志

} break;

} pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;// 下一个等待

事件标志的节点}if (sched == TRUE) OS_Sched();//如果设置了调度标志,则实施调度*err = OS_NO_ERR;

return (pgrp->OSFlagFlags);}

发送(置位)事件标志组中的事件标志 OSFlagPost()

Page 95: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除事件集•回收事件集控制块到空闲链中,等待接收该事件集的任务被恢复就绪

Page 96: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除事件标志组 OSFlagDel()OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp, INT8U opt, INT8U *err){ BOOLEAN tasks_waiting; OS_FLAG_NODE *pnode;

if (pgrp->OSFlagWaitList != (void *)0) tasks_waiting = TRUE;// 有任务等待else tasks_waiting = FALSE;//无任务等待switch (opt) {

case OS_DEL_NO_PEND:// 在无任务等待时才删除事件标志组if (tasks_waiting == FALSE) {//无任务等待,释放控制块到空闲

链中 pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; pgrp->OSFlagWaitList = (void *)OSFlagFreeList;

OSFlagFreeList = pgrp; *err = OS_NO_ERR; return ((OS_FLAG_GRP *)0);} else {// 有任务等待,删除失败 *err = OS_ERR_TASK_WAITING;

return (pgrp); }

Page 97: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

删除事件标志组 OSFlagDel() case OS_DEL_ALWAYS://无论是否有任务等待,都删除事件标志组

pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;// 获取等待头节点

while (pnode != (OS_FLAG_NODE *)0) {//遍历整个等待任务链,使每个等待任务就绪

OS_FlagTaskRdy(pnode, (OS_FLAGS)0); pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; }

pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; pgrp->OSFlagWaitList = (void *)OSFlagFreeList;

OSFlagFreeList = pgrp;// 释放控制块回空闲链if (tasks_waiting == TRUE) OS_Sched();//如果之前有任务等待,

*err = OS_NO_ERR; 内核实施调度 return ((OS_FLAG_GRP *)0); default:

*err = OS_ERR_INVALID_OPT; return (pgrp); }}

Page 98: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

设置事件②

设置事件②

Task1

ISR

来自某设备的中断 Task2

消息队列 Q

事件标志集

信号量 S

0 1 0 0 0 1 0 0

发送消息①

释放信号量①

接收消息④

获取信号量④

事件机制的典型应用•解决复杂的应用设计问题 ①发送方( Task1 或 I

SR)发送信息(消息或信号量);②发送方( Task1 或 ISR)设置相应的事件标志(指示消息或信号量的发送);③接收方( Task2)检测事件标志集,判断是否满足其接收条件(“与”条件接收或“或”条件接收);④接收方( Task2)根据事件标志集的指示定向接收信息(消息或信号量),达到和不同发送方( Task1 或 ISR)同步或通信的目的。

Page 99: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

第四节

异步信号概述异步信号机制与中断机制的比较异步信号机制与事件机制的比较异步信号机制的主要数据结构典型的异步信号操作

Page 100: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

• 异步信号机制用于任务与任务之间、任务与 ISR之间的异步操作,它被任务(或 ISR)用来通知其它任务某个事件的出现。

• 异步信号标志可以依附于任务。需要处理异步信号的任务由两部分组成,一个是与异步信号无关的任务主体,另一个是 ASR(异步信号服务例程)。

• 一个 ASR对应于一个任务。当向任务发送一个异步信号,如果该任务正在运行则中止其自身代码的运行,转而运行与该异步信号相关的服务例程;或者当该任务被激活时,在投入运行前执行 ASR。

• 异步信号机制也可以称作软中断机制,异步信号又被称为软中断信号。

概述

Page 101: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

概述

Task1

ISR

Task2 ( ){使能异步信号;……………………}

Signal_routine ( ){……Return();}

1 0 0 0 0 0

异步信号标志

Page 102: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

异步信号机制与中断机制的比较•相同点

– 具有中断性。对中断的处理和对异步信号的处理都要先暂时地中断当前任务的运行。

– 有相应的服务程序• 根据中断向量,有一段与中断信号对应的服务程序,称为 ISR ( Interrupt Service Routine )

• 根据异步信号的编号,有一段与之对应的服务程序,称为 ASR ( Asynchronious Service Routine )

– 可以屏蔽其响应• 外部硬件中断可以通过相应的寄存器操作被屏蔽• 任务也可屏蔽对异步信号的响应

Page 103: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

异步信号机制与中断机制的比较•不同点

– 实质不同•中断由硬件或者特定的指令产生,不受任务调

度的控制• 异步信号由系统调用(使用发送异步信号功

能)产生,受到任务调度的控制

– 处理时机(或响应时间)不同• 中断触发后,硬件根据中断向量找到相应的服务程序

执行。在退出中断服务程序之前会进行重调度,所以中断结束后运行的任务不一定是先前被中断的任务。

• 异步信号通过发送异步信号的系统调用触发,但是系统不一定马上开始对它的处理:

– 如果接收异步信号的不是当前任务,则 ASR 要等到接收任务被调度、完成上下文切换后才能执行,之后再执行任务自身的代码。

– 任务也可以给自己发送异步信号,在这种情况下,其 ASR 将马上执行。

– 执行的环境不同• 一般地, ISR 在独立的上下文中运行,操作系

统为之提供专门的堆栈空间。• ASR 在相关任务的上下文中运行,所以 ASR

也是任务的一个组成部分。

Page 104: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

异步信号机制与事件机制的比较

•同样是标志着某个事件的发生,事件机制的使用是同步的,而异步信号机制是异步的。– 对一个任务来说,什么时候会接收到事件是

已知的,因为接收事件的功能是它自己在运行过程中调用的。

– 任务不能预知何时会收到一个异步信号,并且一旦接收到了异步信号,在允许响应的情况下,它会中断正在运行的代码而去执行异步信号处理程序。

Page 105: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

异步信号机制的主要数据结构

• 一种异步信号控制结构 Asynchronous_Signal_Control_Block – enabled 是否使能对异步信号的响应– handler 处理例程– attribute_set ASR 的执行属性– signals_posted 使能响应时,已发送但尚未处理的信

号– signals_pending 屏蔽响应时,已发送但尚未处理的

信号– nest_level ASR中异步信号的嵌套层数

Page 106: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

异步信号机制的主要数据结构

• ASR的执行属性– 是否允许任务在执行 ASR 过程中被抢占– 是否允许时间片切换– 是否支持 ASR 嵌套– 是否允许在执行 ASR 过程中响应中断

Page 107: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的异步信号操作

•安装异步信号处理例程•发送异步信号到任务

Page 108: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

安装异步信号处理例程

•为任务安装一个异步信号处理例程( ASR)。仅当任务已建立了 ASR,才允许向该任务发送异步信号,否则发送的异步信号无效。当任务的 ASR 无效时,发送到任务的异步信号将被丢弃。

•调用者需指定 ASR的入口地址和执行属性。

Page 109: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

异步信号处理例程的一般形式

void handler(signal_set){

switch(signal_set){

CASE SIGNAL_1:动作 1 ;break;

 CASE SIGNAL_2:

动作 2 ;break;

……}

}

signal_set 参数为任务接收到的异步信号集。

Page 110: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

发送异步信号到任务• 任务或 ISR可以调用该功能发送异步信号到目标任务,发送者指定目标任务和要发送的异步信号(集)。

• 发送异步信号给任务对接收任务的执行状态没有任何影响。

• 在目标任务已经安装了异步信号处理例程的情况下,如果目标任务不是当前执行任务,则发送给它的异步信号就会等下一次该任务占有处理器时再由相应的 ASR处理,任务获得处理器后,将首先执行 ASR。

• 如果当前运行的任务发送异步信号给自己或收到来自中断的异步信号,在允许 ASR处理的前提下,它的 ASR会立即执行。

Page 111: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

第五节

管道概述管道机制的主要数据结构典型的管道操作管道机制的典型应用

Page 112: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制概述•管道( pipe)是提供非结构化数据交换和实现任务间同步的内核对象。在传统的实现中,管道是单向数据交换设施。

Task1Task1 Task2Task2

管道

管道中的数据

写描述符 读描述符

向管道写数据

从管道读数据

数据在管道内像一个非结构字节流,按 FIFO 的次序从管道中读出。当管道空时,阻塞读者,当管道满时,阻塞写者。

Page 113: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制概述•管道允许有多个读者和写者。

Task1Task1

Task5Task5

管道Task2Task2

Task3Task3Task4Task4

Task6Task6ISR1ISR1ISR2ISR2ISR3ISR3

公共管道操作

Page 114: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制概述• 管道与消息队列的区别

– 管道不存储多个消息,它存储的数据是非结构化的字节流;

– 管道中的数据严格地遵循先进先出的顺序;– 管道支持选择( select )操作,而消息队列

不支持。

Page 115: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制概述•管道的状态

非空 满

创建管道无写入数据

读数据,有剩余数据

写数据

读数据,无数据留下

写数据,有剩余空间

读数据

写数据,无剩余空间

Page 116: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制概述•命名管道和无名管道:

– 一个命名管道具有一个类似于文件名的名字,并像一个文件或设备出现在文件中。任务或 ISR 可以用名字对其进行引用。

– 无名管道没有名字且不在文件系统中出现,它必须使用创建管道时系统返回调用者的描述符才能引用。

Page 117: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制的主要数据结构管道控制块

Byte count

Data buffer

Buffer size

Output position

Input positionTask3 Task4 ……

接收任务等待列表

Task1 Task2 ……

发送任务等待列表

Page 118: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的管道操作•创建和删除一个管道;•读或写管道;•管道上的选择操作;• Flush操作。

Page 119: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的管道操作•管道创建和删除

– 创建管道的操作给调用者返回两个描述符,后续的调用引用这些描述符。一个描述符只能用于写,而另一个只能用于读。

– 创建一个命名管道与创建文件类似,在命名管道建立之后,在文件系统中有一个可识别的名字,可以使用 open 操作打开它。因此,调用者也必须说明是采用读方式打开还是写方式打开。

– 与 open 操作相对应, close 操作用于关闭并删除一个命名管道。

Page 120: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的管道操作•管道读和写

–读操作把管道中的数据返回给调用者(任务)。任务应指定读多少数据。如果指定的大小超过管道中可以得到的数据量,则任务可以选择阻塞,等待剩余的数据到达。

Page 121: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的管道操作•选择( Select)操作

– Select 操作允许一个任务阻塞并等待一个或多个管道上的一个指定条件的发生。

Task1

ISR

Task2

Task3

Pipe1

Pipe2

Pipe3

任务 Task3等待从 Pipe1和 Pipe2 这两个管道读数据并写到第三个管道 Pipe3上。在这种情况下,当头两个管道中的任意一个有数据时, Select调用返回。

Page 122: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

典型的管道操作• Flush操作

– Flush 操作将所有的数据从管道中清除,使管道回到最初创建的状态。

Page 123: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制的典型应用•主要用于任务到任务或 ISR到任务的数据传输

•也可用于任务之间的同步

Page 124: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

管道机制的典型应用

Task A

Task B

Select操作 Select操作

管道 C

管道 D

任务 A和任务 B打开两个管道作为任务间的通信方式:打开管道 C作为从任务 A到任务 B的数据传输,打开管道 D作为从任务 B到任务 A的回应。

Page 125: 嵌入式系统及应用

电子科技大学嵌入式软件工程中心

谢谢!