




已阅读5页,还剩123页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
嵌入式系统及应用,第六章 同步、互斥与通信,主要内容,概述 信号量 邮箱和消息队列 事件 异步信号* 管道*,概述,多任务系统中任务之间的关系 相互独立 仅竞争CPU资源 竞争除CPU外的其他资源(互斥) 同步 协调彼此运行的步调,保证协同运行的各个任务具有正确的执行次序 通信 彼此间传递数据或信息,以协同完成某项工作,任务能以以下方式与中断处理程序或其他任务进行同步或通信: 单向同步或通信:一个任务与另一个任务或一个ISR同步或通信。 双向同步或通信:两个任务相互同步或通信。双向同步不能在任务与ISR之间进行,因为ISR不能等待。,概述,ISR x,Task y,POST,PEND,任务与ISR之间的同步(单向),Task x,Task y,POST,PEND,POST,PEND,任务与任务之间的同步(双向),任务与任务之间的同步(单向),Task x,Task y,POST,PEND,在嵌入式多任务系统中,任务间的耦合程度是不一样的: 耦合程度较高:任务之间需要进行大量的通信,相应的系统开销较大; 耦合程度较低:任务之间不存在通信需求,其间的同步关系很弱甚至不需要同步或互斥,系统开销较小。 研究任务间耦合程度的高低对于合理地设计应用系统、划分任务有很重要的作用。,概述,在单处理器平台上,嵌入式操作系统内核提供的同步、互斥与通信机制主要包括: 信号量(semaphore),用于互斥与同步 事件(组)(event group),用于同步 异步信号(asynchronous signal),用于同步 邮箱(mailbox)、消息队列(message queue),用于消息通信 管道(pipe),提供非结构化数据交换和实现同步,概述,以下一些机制也可用于同步与通信(在单处理器或多处理器系统中): 全局变量 共享内存 Sockets 远程过程调用(Remote Procedure Call),概述,第一节 信号量,信号量的种类及用途 互斥信号量 二值信号量 计数信号量 信号量机制的主要数据结构 典型的信号量操作,信号量用于实现任务与任务之间、任务与中断处理程序之间的同步与互斥。 信号量一般分为三种:,信号量的种类及用途,用于解决互斥问题。它比较特殊,可能会引起优先级反转问题。,用于解决同步问题,用于解决资源计数问题,将信号量进行种类细分,可以根据其用途,在具体 实现时做专门处理,提高执行效率和可靠性。,互斥信号量,计数信号量,二值信号量,用互斥信号量保护的代码区称作“临界区”,临界区代码通常用于对共享资源的访问。 互斥信号量的值被初始化成1,表明目前没有任务进入“临界区”,但最多只有一个任务可以进入“临界区”。 第一个试图进入“临界区”的任务将成功获得互斥信号量,而随后试图进入用同一信号量保护的临界区的所有其他任务就必须等待。 当任务离开“临界区”时,它将释放信号量并允许正在等待该信号量的任务进入“临界区”。,互斥信号量,互斥信号量,共享资源可能是一段存储器空间、一个数据结构或I/O设备,也可能是被两个或多个并发任务共享的任何内容。 使用互斥信号量可以实现对共享资源的串行访问,保证只有成功地获取互斥信号量的任务才能够释放它。 互斥信号量是一种特殊的二值信号量,一般它支持所有权、递归访问、任务删除安全和一些避免优先级反转、饥饿、死锁等互斥所固有问题的协议。,互斥信号量状态图,互斥信号量状态图,开启,锁定,初始化 值为1,申请并获得 值为0,释放 值为1,申请(递归)并获得 锁定数加1,释放(递归) 锁定数减1,互斥信号量,所有权:当一个任务通过获取互斥信号量而将其锁定时,得到该互斥信号量的所有权。相反,当一个任务释放信号量时,失去对其的所有权。 当一个任务拥有互斥信号量时,其他的任务不能再锁定或释放它,即任务要释放互斥信号量,必须事前先获取该信号量。,Task1,RoutineA,RoutineB,互斥信号量,嵌套(递归)资源访问 如果Task1调用RoutineA,而RoutineA又调用RoutineB,并且三者访问相同的共享资源,就发生了递归共享资源的访问同步问题。,一个递归的互斥信号量允许嵌套锁定互斥信号量,而不引起死锁。,互斥信号量,嵌套(递归)资源访问 每个获取信号量的调用必须与释放信号量的调用相匹配。当最外层的获取信号量的调用与释放信号量的调用匹配时,该信号量才允许被其它任务访问。 用于同步的信号量不支持嵌套访问,任务如果对同步信号量使用上述操作是错误的,任务会被永久阻塞,并且阻塞条件永远不会解除。,互斥信号量,删除安全: 在一个受信号量保护的临界区,经常需要保护在临界区执行的任务不会被意外地删除。 删除一个在临界区执行的任务可能引起意想不到的后果,造成保护资源的信号量不可用,可能导致资源处于破坏状态,也就导致了其它所有要访问该资源的任务无法得到满足。,互斥信号量,删除安全: 为避免任务在临界区执行时不被意外删除: 提供“任务保护”和“解除任务保护”原语对 同时,为互斥信号量提供“删除安全”选项。在创建信号量的时候使用这个选项,当应用每次获取信号量时隐含地使能“任务保护”功能,当每次释放信号量时隐含地使用“解除任务保护”功能。,各种互斥机制比较,二值信号量,二值信号量主要用于任务与任务之间、任务与中断服务程序之间的同步 用于同步的二值信号量初始值为0,表示同步事件尚未产生; 任务申请信号量以等待该同步事件的发生; 另一个任务或ISR到达同步点时,释放信号量(将其值设置为1)表示同步事件已发生,以唤醒等待的任务。,二值信号量,二值信号量状态图,可获得,不可获得,申请并获得 (值为0),释放 (值为1),初始化 值为0,Task1() 执行一些操作; 将信号量sem1置1; 申请信号量sem2; ,Task2() 申请信号量sem1; 执行一些操作; 将信号量sem2置1; ,Task2申请信号量sem1失败,系统切换到Task1,sem1被置1后,Task2得到sem1并抢占Task1,Task2运行到某处时因某种原因被阻塞,系统切换到Task1,用二值信号量实现两个任务之间的双向同步 Task2优先级高于Task1 sem1和sem2的初始值均为0,计数信号量,计数信号量用于控制系统中共享资源的多个实例的使用,允许多个任务同时访问同一种资源的多个实例 计数信号量被初始化为n(非负整数),n为该种共享资源的数目。,计数信号量,计数信号量状态图,可获得,不可获得,初始化 值大于0,申请并获得 值为0,释放 值为1,申请并获得 值减1,释放 值加1,计数信号量,计数信号量使用实例:有界缓冲问题,生产者任务 do 产生一个数据项 申请empty 申请mutex 将新生成的数据项添加到缓冲中 释放mutex 释放full while (1);,消费者任务 do 申请full 申请mutex 从缓冲中移出一个数据项的内容 释放mutex 释放empty 消费新获得的数据项内容 while (1);,计数信号量full:已被填充的数据项数目,取值范围0n,初始值为0 计数信号量empty:空闲数据项数目,取值范围为0n,初始值为n; 互斥信号量mutex:控制生产者任务和消费者任务对有界缓冲的访问,初始值为1。,信号量机制的主要数据结构,信号量机制的主要数据结构,信号量控制块:管理所有创建的信号量,内核在系统运行时动态分配和回收信号量控制块 互斥和二值信号量控制块结构: Binary_Semaphore_Control_Block,wait_queue 任务等待队列 attributes 信号量属性 lock_nesting_behavior试图嵌套获得时的规则 wait_discipline 任务等待信号量的方式 priority_ceiling 优先级天花板值 lock 是否被占有 holder 拥有者 nest_count 嵌套层数,计数信号量控制结构Counting_Semaphore_Control_Block wait_queue 任务等待队列 attributes 计数信号量属性 maximum_count 最大计数值 wait_discipline 任务等待信号量的方式 count 当前计数值,信号量机制的主要数据结构,信号量内部实现机制实例说明 C/OS-II,事件控制块ECB同步与通信机制的基本数据结构 typedef struct INT8U OSEventType;/事件类型 INT8U OSEventGrp;/等待任务所在的组 INT16U OSEventCnt;/计数器(信号量) void *OSEventPtr;/指向消息或消息队列的指针 INT8U OSEventTblOS_EVENT_TBL_SIZE;/等待任务列表 OS_EVENT;,信号量内部实现机制实例说明 C/OS-II,当一个事件发生后,等待事件列表中优先级最高的任务(即在.OSEventTbl&OSEventGrp中所有被置1的位中优先级数值最小的任务)得到该事件。,信号量内部实现机制实例说明 C/OS-II,当.OSEventTbln中的任何一位为1时,OSEventGrp中的第n位为1。 与任务就绪列表类似!,信号量内部实现机制实例说明 C/OS-II,将一个任务插入到等待事件的任务列表中: pevent-OSEventGrp |= OSMapTblprio 3; pevent-OSEventTblprio 3 |= OSMapTblprio 与将一个任务插入到就绪列表中的操作类似!,Index Bit mask (Binary) 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 2 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,信号量内部实现机制实例说明 C/OS-II,从等待事件的任务列表中使任务脱离等待状态 if (pevent-OSEventTblprio 3 与将任务从就绪列表中清除的操作类似!,信号量内部实现机制实例说明 C/OS-II,在等待事件的任务列表中查找优先级最高的任务 y = OSUnMapTblpevent-OSEventGrp; x = OSUnMapTblpevent-OSEventTbly; prio = (y 3) + x; 与查找优先级最高的就绪任务的操作类似!,信号量内部实现机制实例说明 C/OS-II,空闲事件控制块链表,典型的信号量操作,创建信号量 获取(申请)信号量 释放信号量 删除信号量 清除信号量的任务等待列表 获取有关信号量的各种信息,创建信号量,功能:根据应用传递的参数创建一个信号量 参数:信号量的名字、属性和初始值等。 内核动作: 从空闲信号量控制块链中分配一个信号量控制块,并初始化信号量属性。 创建成功时,为其分配唯一的ID号返回给应用。 如果已创建信号量数量已达到用户配置的最大数量,就返回错误。,创建信号量,信号量的属性包括: 类型 任务等待信号量的方式(即排列的顺序) 与任务删除安全、递归访问以及解决优先级反转的策略相关的参数(只针对互斥信号量)。,创建信号量,信号量的属性,信号量的类型,互斥信号量(MUTEX_SEMAPHORE),计数信号量(COUNTING_SEMAPHORE),二值信号量(BINARY_SEMAPHORE),任务等待信号量的方式,先进先出(FIFO)顺序,优先级(PRIORITY)顺序,优先级反转问题的解决方法(只适用于互斥信号量),优先级继承算法(INHERIT_PRIORITY),优先级天花板算法(PRIORITY_CEILING) ,需给出所有可能获得此信号量的任务中优先级最高的任务的优先级。,创建一个信号量OSSemCreate(),OS_EVENT *OSSemCreate (INT16U cnt) OS_EVENT *pevent; pevent = OSEventFreeList;/从空闲事件控制块链中取得一个ECB if (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则表示建立失败 ,获取(申请)信号量,功能:试图获得应用指定的信号量。 if 信号量的值大于0 then 将信号量的值减1 else 根据接收信号量的选项,将任务放到等待队列中,或是直接返回,获取(申请)信号量,当所申请的信号量不能被立即获得时,可以有以下几种选择: 永远等待 不等待,立即返回,并返回一个错误状态码 指定等待时限(可有效避免死锁) 注意: 不允许在ISR中选择等待 当任务选择等待时,将被按FIFO或优先级顺序放置在等待队列中,获取(申请)信号量,如果任务等待一个使用优先级继承算法的互斥信号量,且它的优先级高于当前正占有此信号量的任务的优先级,那么占有信号量的任务将继承这个被阻塞的任务的优先级。 如果任务成功地获得一个采用优先级天花板算法的互斥信号量,它的优先级又低于优先级天花板,那么它的优先级将被抬升至天花板。,获取(等待)一个信号量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 /任务由于获得信号量而恢复执行,本调用成功返回 ,获取(无等待地请求)一个信号量OSSemAccept(),INT16U OSSemAccept (OS_EVENT *pevent) INT16U cnt; cnt = pevent-OSEventCnt; if (cnt 0) pevent-OSEventCnt-; return (cnt); ,注意:即使不能成功获得信号量(返回值为0),调用者也不会被阻塞。此函数可以在中断处理程序中使用。,释放信号量,功能:释放一个应用指定的信号量。 if 没有任务等待这个信号量 then 信号量的值加1 else 将信号量分配给一个等待任务(将相应的任务移出等待队列,使其就绪) 如果使用了优先级继承或优先级天花板算法,那么执行该功能(系统调用)的任务的优先级将恢复到原来的高度。,释放一个信号量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 OSEventCnt+; /信号量的值加1 return (OS_NO_ERR);/成功返回 return (OS_SEM_OVF);/信号量溢出 ,删除信号量,功能:从系统中删除应用指定的一个信号量 内核动作:将信号量控制块返还给系统 删除信号量的不一定是创建信号量的任务 如果有任务正在等待获得该信号量,执行此功能将使所有等待这个信号量的任务回到就绪队列中,且返回一个状态码指示该信号量已被删除,删除信号量,企图获取已删除的信号量将返回一个错误; 在互斥信号量正被使用时(已经被某任务获取),不能删除它。因为该信号量正在保护一个共享资源或临界代码段,该动作可能造成数据崩溃或其他严重问题。,删除一个信号量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); ,删除一个信号量OSSemDel(),case OS_DEL_ALWAYS:/无论有无任务等待都删除信号量 /将等待列表中的每个任务都设置成就绪 while(pevent-OSEventGrp!=0x00) OS_EventTaskRdy(pevent,(void *)0, OS_STAT_SEM); /释放该信号量的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); ,清除信号量的任务等待列表,为了清除等待一个信号量的所有任务,某些内核支持Flush操作,以便释放信号量等待任务列表中的所有任务。当多个任务的执行必须在某些点相遇时,需要这样的机制。,第二节 邮箱和消息队列,通信方式概述 消息队列机制的主要数据结构 典型的消息队列操作 消息队列的其他典型使用,任务间的通信方式 直接通信。在通信过程中双方必须明确地知道(命名)彼此: Send (P,message) 发送一个消息到任务P Receive(Q,message) 从任务Q接收一个消息 间接通信。通信双方不需要指出消息的来源或去向,而通过中间机制来通信。如: send(A,message) 发送一个消息给邮箱A receive(A,message) 从邮箱A接收一个消息,通信方式概述,消息队列:属于间接通信方式 消息:内存空间中一段长度可变的缓冲区,其长度和内容均可以由用户定义,其内容可以是实际的数据、数据块的指针或空。 对消息内容的解释由应用完成。 从操作系统观点看,消息没有定义的格式,所有的消息都是字节流,没有特定的含义。 从应用观点看,根据应用定义的消息格式,消息被解释成特定的含义。 应用可以只把消息当成一个标志,这时消息机制用于实现同步,概述,一些操作系统内核把消息进一步分为:邮箱和消息队列 邮箱仅能存放单条消息,它提供了一种低开销的机制来传送信息。每个邮箱可以保存一条大小为若干个字节的消息。 消息队列可存放若干消息,提供了一种任务间缓冲通信的方法。 消息机制可支持定长与可变长度两种模式的消息,可变长度的消息队列需要对队列中的每一条消息增加额外的存储开销。,概述,消息队列机制的主要数据结构,消息队列及其相关的参数和支持数据结构,消息队列状态图,非空,满,队列创建 消息数为0,消息队列状态图,消息发送 消息数加1,空,消息发送 消息数为1,消息接收 消息数为0,消息接收 消息数减1,消息接收 消息数减1,消息发送 消息数等于队列长度,消息队列机制的主要数据结构,消息队列控制块 管理所有创建的消息队列,系统运行时动态分配和回收消息队列控制块 消息队列缓冲区 存放发送到该队列的消息,接收者从缓冲区中取出消息。 消息的发送或接收有两种方法(影响消息缓冲区结构): 将数据从发送任务的空间完全拷贝到接收任务的空间中(效率较低,执行时间与消息大小有关) 只传递指向数据存储空间的指针(提高系统性能),发送和接收消息的消息拷贝和内存使用 这种消息传递方法效率低、占用空间大 一种效率更高的方式是传递消息指针,number_of_message,max_message_count,消息队列控制块,消息队列缓冲区,消息队列机制的主要数据结构,消息队列的环形缓冲,消息队列机制的主要数据结构,max_message_count,queue_end,queue_start,queue_out,number_of_message,queue_in,消息指针,典型的消息队列操作,创建消息队列 发送普通消息 发送紧急消息 发送广播消息 接收消息 删除消息队列 获取有关消息队列的各种信息,创建消息队列,创建消息队列时,调用者可以指定如下参数: 消息的最大长度 每个消息队列中最多的消息数 消息队列的属性 任务等待消息时的排队方式:FIFO或PRIORITY 系统为新创建的消息队列分配唯一的ID,发送消息,根据紧急程度的不同,消息通常可分为普通消息与紧急消息。 如果有任务正在等待消息(即消息队列为空),则普通消息发送和紧急消息发送的执行效果是一样的。任务从等待队列移到就绪队列中,消息被拷贝到任务提供的缓冲区中(或者由接收任务得到指向消息的指针)。 如果没有任务等待,发送普通消息将消息放在队列尾,而发送紧急消息将消息放在队列头。,发送消息,发送消息,如果发送消息时队列已被填满,则不同的操作系统可能采取不同的处理办法: 挂起试图向已满的消息队列中发送消息的任务(不适用于中断服务程序) 简单地丢弃该条消息并向调用者返回错误信息 广播消息。在此之前所有试图从队列中接收消息的任务此时都将获得相同的消息。该功能拷贝消息到各任务的消息缓冲中(或者让所有的等待任务得到指向消息的指针),并唤醒所有的等待任务。,接收消息,如果指定的消息队列中有消息,则将其中的第一条消息拷贝到调用者的缓冲区(或者将第一条消息指针传递给调用者),并从消息队列中删除它。 如果此时消息队列中没有消息,则可能出现以下几种情况: 永远等待消息的到达:等待消息的任务按FIFO或优先级高低顺序排列在等待队列中 等待消息且指定等待时限:等待消息的任务按FIFO或优先级高低顺序排列在等待队列中 不等待,强制立即返回,接收消息,限时等待可有效预防死锁 中断服务程序接收消息时必须选择不等待,因为中断服务程序是不能被阻塞的。 如果消息队列被应用删除,则所有等待该消息队列的任务都被返回一个错误信息,并回复到就绪状态。,接收消息,删除消息队列,从系统中删除指定的消息队列,释放消息队列控制块及消息队列缓冲区。 任何知道此消息队列ID号的代码都可以删除它。 消息队列被删除后,所有等待从这个消息队列接收消息的任务都回到就绪态,并得到一个错误信息表明消息队列已被删除。,消息队列的其他典型使用,紧耦合的单向数据通信:发送任务发送消息后要求一个响应信号,表明接收任务已经成功接收到消息。,消息队列的其他典型使用,紧耦合的双向数据通信 :如果数据需要在任务之间双向流动,则可以采用紧耦合的双向数据通信模式(也称为全双工通信)。,第三节 事 件,概述 事件机制的主要数据结构 典型的事件操作 事件机制的典型应用,在嵌入式实时内核中,事件是指一种表明预先定义的系统事件已经发生的机制。 事件机制用于任务与任务之间、任务与ISR之间的同步。其主要的特点是可实现一对多的同步。 一个事件就是一个标志,不具备其它信息。 一个或多个事件构成一个事件集。事件集可以用一个指定长度的变量(比如一个8bit, 16bit或32bit的无符号整型变量,不同的操作系统其具体实现不一样)来表示,而每个事件由在事件集变量中的某一位来代表。,概述,事件及事件集有以下特点: 事件间相互独立 事件仅用于同步,不提供数据传输功能 事件无队列,即多次发送同一事件,在未经过任何处理的情况下,其效果等同于只发送一次。 提供事件机制的意义在于: 当某任务要与多个任务或中断服务同步时,就需要使用事件机制。 若任务需要与一组事件中的任意一个发生同步,可称为独立型同步(逻辑“或”关系)。 任务也可以等待若干事件都发生时才同步,称为关联型同步(逻辑“与”关系)。,概述,“或”同步和“与”同步,概述,任务,任务,任务,任务,ISR,ISR,OR,AND,“与”型同步,“或”型同步,事件集,事件集,POST,POST,PEND,PEND,用多个事件的组合发信号给多个任务,概述,任务,任务,任务,ISR,OR,AND,事件集,事件集,事件集 (8,16或32位),POST,PEND,PEND,术语: 发送事件集 。指在一次发送过程中发往接收者(比如任务)的一个或多个事件的组合。 待处理事件集。指已被发送到一个接收者但还没有被接收(即正在等待处理)的所有事件的集合。 事件条件。指事件接收者在一次接收过程中期待接收的一个或多个事件的集合。 “或”同步:待处理事件集只要包括事件条件中的任一事件即可满足要求; “与”同步:其二是待处理事件集必须包括事件条件中的全部事件方可满足要求。,概述,事件机制的主要数据结构,事件集控制块:管理所有创建的事件集 或者 事件集附属于任务,不需创建,其相关参数成为任务控制块的一部分,事件的内部实现机制实例说明 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;,事件标志组、事件标志节点及 任务控制块之间的关系,OS_FLAG_GRP,OS_FLAG_NODE,.OSTCBFlagNode .OSFlagNodeFlags .OSFlagNodeWaitType .OSFlagNodeNext .OSFlagNodePrev .OSFlagNodeTCB,.OSFlagWaitList .OSFlagFlags .OSFlagType,AND or OR,AND or OR,AND or OR,OS_EVENT_TYPE_FLAG,0,0,.OSTCBFlagNode,OS_TCB,典型的事件操作,创建事件集 删除事件集 发送事件(集) 接收事件(集) 获取有关事件集的各种信息,创建事件集,申请空闲事件集控制块,设置事件集属性,初始化控制块中的域,分配ID号,创建一个事件标志组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); ,接收事件(集),在接收事件(集)时可以有如下选项,接收(等待)事件标志组的事件标志位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,接收(等待)事件标志组的事件标志位OSFlagPend(),case OS_FLAG_WAIT_SET_ANY: /任务以“或”方式等待事件标志 flags_rdy=pgrp-OSFlagFlags ,OS_Sched();/当前任务被放到事件标志等待链后,内核实施任务调度 if(OSTCBCur-OSTCBStat ,接收(等待)事件标志组的事件标志位OSFlagPend(),添加一个任务到事件标志组等待任务链表中OS_FlagBlock(),OS_FLAG_GRP,OS_EVENT_TYPE_FLAG,AND or OR,AND or OR,0,0,OS_TCB,OS_TCB,OSTCBCur,OS_FLAG_NODE,0,接收(无等待地获取)事件标志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 ,接收(无等待地获取)事件标志OSFlagAccept(),case OS_FLAG_WAIT_SET_ANY:/”或”方式等待 flags_rdy = pgrp-OSFlagFlags ,发送事件(集),调用者(任务或中断)构造一个事件(集),将其发往接收者(比如目标任务)。可能会出现以下几种情况之一: 目标任务正在等待的事件条件得到满足,任务就绪; 目标任务正在等待的事件条件没有得到满足,该事件(集)被按“或”操作,保存到目标任务的待处理事件集中,目标任务继续等待; 目标任务未等待事件(集),该事件(集)被按“或”操作,保存到目标任务的待处理事件集中。,发送(置位)事件标志组中的事件标志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 ,case OS_FLAG_WAIT_SET_ANY:/”或”方式等待 flags_rdy = pgrp-OSFlagFlags ,发送(置位)事件标志组中的事件标志OSFlagPost(),删除事件集,回收事件集控制块到空闲链中,等待接收该事件集的任务被恢复就绪,删除事件标志组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); ,删除事件标志组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); ,设置事件,设置事件,Task1,ISR,来自某设备的中断,Task2,消息队列Q,事件标志集,信号量S,0,1,0,0,0,1,0,0,发送消息,释放信号量,接收消息,获取信号量,事件机制的典型应用,解决复杂的应用设计问题,发送方(Task1或ISR)发送信息(消息或信号量); 发送方(Task1或ISR)设置相应的事件标志(指示消息或信号量的发送); 接收方(Task2)检测事件标志集,判断是否满足其接收条件(“与”条件接收或“或”条件接收); 接收方(Task2)根据事件标志集的指示定向接收信息(消息或信号量),达到和不同发送方(Task1或ISR)同步或通信的目的。,第四节 异步信号,概述 异步信号机制与中断机制的比较 异步信号机制与事件机制的比较 异步信号机制的主要数据结构 典型的异步信号操作,异步信号机制用于任务与任务之间、任务与ISR之间的异步操作,它被任务(或ISR)用来通知其它任务某个事件的出现。 异步信号标志可以依附于任务。需要处理异步信号的任务由两部分组成,一个是与异步信号无关的任务主体,另一个是ASR(异步信号服务例程)。 一个ASR对应于一个任务。当向任务发送一个异步信号,如果该任务正在运行则中止其自身代码的运行,转而运行与该异步信号相关的服务例程;或者当该任务被激活时,在投入运行前执行ASR。 异步信号机制也可以称作软中断机制,异步信号又被称为软中断信号。,概述,概述,异步信号机制与中断机制的比较,相同点 具有中断性。对中断的处理和对异步信号的处理都要先暂时地中断当前任务的运行。 有相应的服务程序 根据中断向量,有一段与中断信号对应的服务程序,称为ISR(Interrupt Service Routine) 根据异步信号的编号,有一段与之对应的服务程序,称为ASR(Asynchronious Service Routine) 可以屏蔽其响应 外部硬件中断可以通过相应的寄存器操作被屏蔽 任务也可屏蔽对异步信号的响应,异步信号机制与中断机制的比较,不同点 实质不同 中断由硬件或者特定的指令产生,不受任务调度的控制 异步信号由系统调用(使用发送异步信号功能)产生,受到任务调度的控制,处理时机(或响应时间)不同 中断触发后,硬件根据中断向量找到相应的服务程序执行。在退出中断服务程序之前会进行重调度,所以中断结束后运行的任务不一定是先前被中断的任务。 异步信号通过发送异步信号的系统调用触发,但是系统不一定马上开始对它的处理: 如果接收异步信号的不是当前任务,则ASR要等到接收任务被调度、完成上下文切换后才能执行,之后再执行任务自身的代码。 任务也可以给自己发送异步信号,在这种情况下,其ASR将马上执行。,执行的环境不同 一般地,ISR在独立的上下文中运行,操作系统为之提供专门的堆栈空间。 ASR在相关任务的上下文中运行,所以ASR也是任务的一个组成部分。,异步信号机制与事件机制的比较,同样是标志着某个事件的发生,事件机制的使用是同步的,而异步信号机制是异步的。 对一个任务来说,什么时候会接收到事件是已知的,因为接收事件的功能是它自己在运行过程中调用的。 任务不能预知何时会收到一个异步信号,并且一旦接收到了异步信号,在允许响应的情况下,它会中断正在运行的代码而去执行异步信号处理程序。,异步信号机制的主要数据结构,一种异步信号控制结构Asynchronous_Signal_Control_Block enabled 是否使能对异步信号的响应 handler 处理例程 attribute_set ASR的执行属性 signals_posted 使能响应时,已发送但尚未处理的信号 signals_pending 屏蔽响应时,已发送但尚未处理的信号 nest_level ASR中异步信号的嵌套层数,异步信号机制的主要数据结构,ASR的执行属性 是否允许任务在执行A
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年建筑师执照考试试题及答案
- 池河镇九年级化学上册 2.3 构成物质的微粒(Ⅱ)-原子和离子说课稿 (新版)粤教版
- 四年级信息技术下册 第9课 制作“广东风情游”导游图说课稿 粤教版
- 护理安全事件案例分析试题
- 辽宁省七校协作体高三上学期期初联考试题化学
- Unit 3 Toms Diary说课稿小学英语五年级上册新世纪版
- Module 5Unit 1说课稿 2025-2026学年外研版英语八年级下册
- 2025【各类企业合同范本】-【标准合同协议模板】解除合同最佳样本
- Unit 4 Whats in说课稿高中英语教科版必修二-教科版2016
- 我的课外劳动日记(五)说课稿小学劳动人教版六年级上册-人教版
- 先心病介入封堵治疗
- 数控heidenhain说明书TNC直接提供两种加工孔模板的循环
- GB/T 42453-2023信息安全技术网络安全态势感知通用技术要求
- JJG 860-2015压力传感器(静态)
- GB/T 22231-2008颗粒物粒度分布/纤维长度和直径分布
- GB/T 18253-2000钢及钢产品检验文件的类型
- GB 5009.3-2016食品安全国家标准食品中水分的测定
- 液化气站安全生产目标考核与奖惩记录
- 高中生励志奋斗与梦想课件
- 《中职地理》配套教学课件
- 最全可自由编辑的中国各省市地图课件
评论
0/150
提交评论