嵌入式系统开发-Chapter6-同步、互斥 与通信

上传人:biao****biao 文档编号:242969799 上传时间:2024-09-13 格式:PPT 页数:128 大小:1.29MB
返回 下载 相关 举报
嵌入式系统开发-Chapter6-同步、互斥 与通信_第1页
第1页 / 共128页
嵌入式系统开发-Chapter6-同步、互斥 与通信_第2页
第2页 / 共128页
嵌入式系统开发-Chapter6-同步、互斥 与通信_第3页
第3页 / 共128页
点击查看更多>>
资源描述
Click to edit Master title style,Click to edit Master text styles,Second level,Third level,Fourth level,Fifth level,*,电子科技大学嵌入式软件工程中心,嵌入式系统开发,第六章,同步、互斥与通信,主要内容,概述,信号量,邮箱和消息队列,事件,异步信号*,管道*,概述,多任务系统中任务之间,/,任务与,ISR,的关系,相互独立,仅竞争,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,,表明目前没有任务进入,“,临界区,”,,但最多只有一个任务可以进入,“,临界区,”,。,第一个试图进入,“,临界区,”,的任务将成功获得互斥信号量,而随后试图进入用同一信号量保护的临界区的所有其他任务就必须等待。,当任务离开,“,临界区,”,时,它将释放信号量并允许正在等待该信号量的任务进入,“,临界区,”,。,互斥信号量,Task1,Task2,共享资源,互斥信号量,共享资源可能是一段存储器空间、一个数据结构或,I/O,设备,也可能是被两个或多个并发任务共享的任何内容。,使用互斥信号量可以实现,对共享资源的串行访问,,保证只有成功地获取互斥信号量的任务才能够释放它。,互斥信号量是一种特殊的二值信号量,一般它支持,所有权,、,递归访问,、,任务删除安全,和一些,避免优先级反转、饥饿、死锁等互斥所固有问题的协议,。,互斥信号量状态图,互斥信号量状态图,开启,锁定,初始化,值为,1,申请并获得,值为,0,释放,值为,1,申请,(,递归,),并获得,锁定数加,1,释放,(,递归,),锁定数减,1,互斥信号量,所有权,:当一个任务通过获取互斥信号量而将其锁定时,得到该互斥信号量的所有权。相反,当一个任务释放信号量时,失去对其的所有权。,当一个任务拥有互斥信号量时,其他的任务不能再锁定或释放它,即任务要释放互斥信号量,必须事前先获取该信号量。,Task1,RoutineA,RoutineB,互斥信号量,嵌套(递归)资源访问,如果,Task1,调用,RoutineA,,而,RoutineA,又调用,RoutineB,,并且三者访问相同的共享资源,就发生了递归共享资源的访问同步问题,。,共享资源,一个递归的互斥信号量允许嵌套锁定互斥信号量,而不引起死锁。,互斥信号量,嵌套(递归)资源访问,每个获取信号量的调用必须与释放信号量的调用相匹配。当最外层的获取信号量的调用与释放信号量的调用匹配时,该信号量才允许被其它任务访问。,用于同步的信号量不支持嵌套访问,任务如果对同步信号量使用上述操作是错误的,任务会被永久阻塞,并且阻塞条件永远不会解除。,互斥信号量,删除安全:,在一个受信号量保护的临界区,经常需要保护在临界区执行的任务不会被意外地删除。,删除一个在临界区执行的任务可能引起意想不到的后果,造成保护资源的信号量不可用,可能导致资源处于破坏状态,也就导致了其它所有要访问该资源的任务无法得到满足。,互斥信号量,删除安全:,为避免任务在临界区执行时不被意外删除:,提供“任务保护”和“解除任务保护”原语对,同时,为互斥信号量提供,“删除安全”,选项。在创建信号量的时候使用这个选项,当应用每次获取信号量时隐含地使能“任务保护”功能,当每次释放信号量时隐含地使用“解除任务保护”功能。,各种互斥机制比较,比较项目,关中断,使用测试并置位指令,禁止任务,切换,使用信号量,锁定范围,互斥力度最强,,锁定所有外部可屏蔽中断,凡是以中断形式到达的外部事件以及与之相关联的任务或处理过程均得不到执行,凡是使用该指令访问共享资源的代码,所有的任务,只影响竞争共享资源的任务,对系统响应时间的影响,如果关中断的时间较长,对系统的响应性能有很大影响,较小,如果禁止切换的时间过长,则影响系统的响应性能,对系统响应性能有一定影响,,可能导致优先级反转,实现时的系统开销,小,小,小,较大,注意事项,关中断时间要尽量短,不是所有的处理器都具备这种指令,影响可移植性,关调度的时间要尽量短,需采用一定的策略解决优先级反转问题,二值信号量,二值信号量主要用于,任务与任务之间,、,任务与中断服务程序,之间的同步,用于同步的二值信号量,初始值为,0,,表示同步事件尚未产生;,任务,申请信号量,以等待该同步事件的发生;,另一个任务或,ISR,到达同步点时,,释放信号量,(将其值设置为,1,)表示同步事件已发生,以唤醒等待的任务。,Task1,Task2,二值信号量,初值为,0,二值信号量,二值信号量状态图,可获得,不可获得,申请并获得,(,值为,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,为该种共享资源的数目。,Task1,Task2,共享资源实例,n,Task m,共享资源实例,1,计数信号量,计数信号量状态图,可获得,不可获得,初始化,值大于,0,申请并获得,值为,0,释放,值为,1,申请并获得,值减,1,释放,值加,1,计数信号量,1 2 3 4 n,生产者任务,消费者任务,计数信号量使用实例:有界缓冲问题,生产者任务,do,产生一个数据项,申请,empty,申请,mutex,将新生成的数据项添加到缓冲中,释放,mutex,释放,full, while (1);,消费者任务,do,申请,full,申请,mutex,从缓冲中移出一个数据项的内容,释放,mutex,释放,empty,消费新获得的数据项内容, while (1);,计数信号量,full,:已被填充的数据项数目,取值范围,0,n,,初始值为,0,计数信号量,empty,:空闲数据项数目,取值范围为,0,n,,初始值为,n,;,互斥信号量,mutex,:控制生产者任务和消费者任务对有界缓冲的访问,初始值为,1,。,信号量机制的主要数据结构,SCB1,SCB2,信号量控制块,count,信号量名字或,ID,Task1,Task2,任务等待列表,信号量机制的主要数据结构,信号量控制块,:管理所有创建的信号量,内核在系统运行时动态分配和回收信号量控制块,互斥和二值信号量控制块结构,: 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,INT8UOSEventType,;/,事件类型,INT8UOSEventGrp,;/,等待任务所在的组,INT16UOSEventCnt,;/,计数器(信号量),void*OSEventPtr,;/,指向消息或消息队列的指针,INT8UOSEventTblOS_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 &= OSMapTblprio & 0x07) = 0) ,pevent-OSEventGrp ,与将任务从就绪列表中清除的操作类似!,信号量内部实现机制实例说明,C/OS-II,在等待事件的任务列表中查找优先级最高的任务,y = OSUnMapTblpevent-OSEventGrp;,x = OSUnMapTblpevent-OSEventTbly;,prio = (y 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 & OS_STAT_SEM) ,/,判断任务恢复执行的原因,如果等待时限超时但仍然未获得信号量,则返回超时信息,OSEventTO(pevent);,*err = OS_TIMEOUT;,return;,OSTCBCur-OSTCBEventPtr = (OS_EVENT *)0;,*err = OS_NO_ERR;,/,任务由于获得信号量而恢复执行,本调用成功返回,获取(无等待地请求)一个信号量,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,操作,以便释放信号量等待任务列表中的所有任务。当多个任务的执行必须在某些点相遇时,需要这样的机制。,SignalTask,Task2,二值信号量,初值为,0,Flush,Task1,Task3,第二节邮箱和消息队列,通信方式概述,消息队列机制的主要数据结构,典型的消息队列操作,消息队列的其他典型使用,任务间的通信方式,直接通信,。在通信过程中双方必须明确地知道(命名)彼此:,Send (P,,,message) ,发送一个消息到任务,P,Receive(Q,,,message) ,从任务,Q,接收一个消息,间接通信,。通信双方不需要指出消息的来源或去向,而通过中间机制来通信。如:,send(A,,,message) ,发送一个消息给邮箱,A,receive(A,,,message) ,从邮箱,A,接收一个消息,通信方式概述,消息队列:,属于间接通信方式,消息:,内存空间中一段长度可变的缓冲区,其长度和内容均可以由用户定义,其内容可以是实际的数据、数据块的指针或空。,对消息内容的解释由应用完成。,从,操作系统,观点看,消息没有定义的格式,所有的消息都是字节流,没有特定的含义。,从,应用,观点看,根据应用定义的消息格式,消息被解释成特定的含义。,应用可以只把消息当成一个标志,这时消息机制用于实现,同步,概述,一些操作系统内核把消息进一步分为:邮箱和消息队列,邮箱,仅能存放单条消息,它提供了一种低开销的机制来传送信息。每个邮箱可以保存一条大小为若干个字节的消息。,消息队列,可存放若干消息,提供了一种任务间缓冲通信的方法。,消息机制可支持,定长,与,可变长度,两种模式的消息,可变长度的消息队列需要对队列中的每一条消息增加额外的存储开销。,概述,消息队列机制的主要数据结构,队列控制块,队列长度,QCB1,队列名或,ID,Task3,Task4,接收任务等待列表,Task1,Task2,发送任务等待列表,最大,消息,长度,QCB2,消息队列及其相关的参数和支持数据结构,消息队列状态图,非空,满,队列创建,消息数为,0,消息队列状态图,消息发送,消息数加,1,空,消息发送,消息数为,1,消息接收,消息数为,0,消息接收,消息数减,1,消息接收,消息数减,1,消息发送,消息数等于队列长度,消息队列机制的主要数据结构,消息队列控制块,管理所有创建的消息队列,系统运行时动态分配和回收消息队列控制块,消息队列缓冲区,存放发送到该队列的消息,接收者从缓冲区中取出消息。,消息的发送或接收有两种方法(影响消息缓冲区结构):,将数据从发送任务的空间完全拷贝到接收任务的空间中(效率较低,执行时间与消息大小有关),只传递指向数据存储空间的指针(提高系统性能),Sending Task,Receiving Task,Message1,Message1,Message1,发送任务的,内存区域,消息队列的,内存区域,接收任务的,内存区域,1,st,copy,2,nd,copy,发送和接收消息的消息拷贝和内存使用,这种消息传递方法效率低、占用空间大,一种效率更高的方式是传递消息指针,number_of_message,max_message_count,number_of_message,max_message_size,wait_discipline,wait_queue,queue_start,queue_in,queue_out,queue_end,message,message,message,message,message,message,message,message,message,max_message_count,消息队列控制块,消息队列缓冲区,消息队列机制的主要数据结构,消息队列的环形缓冲,消息队列机制的主要数据结构,max_message_count,queue_end,queue_start,queue_out,number_of_message,queue_in,消息指针,典型的消息队列操作,创建消息队列,发送普通消息,发送紧急消息,发送广播消息,接收消息,删除消息队列,获取有关消息队列的各种信息,创建消息队列,创建消息队列时,调用者可以指定如下参数:,消息的最大长度,每个消息队列中最多的消息数,消息队列的属性,任务等待消息时的排队方式:,FIFO,或,PRIORITY,系统为新创建的消息队列分配唯一的,ID,发送消息,根据紧急程度的不同,消息通常可分为,普通消息,与,紧急消息,。,如果有任务正在等待消息(即消息队列为空),则普通消息发送和紧急消息发送的执行效果是一样的。,任务从等待队列移到就绪队列中,消息被拷贝到任务提供的缓冲区中(或者由接收任务得到指向消息的指针),。,如果没有任务等待,发送普通消息将消息放在队列尾,而发送紧急消息将消息放在队列头。,发送消息,Msg 3,接收任务,等待列表,Msg 2,Msg 1,消息队列,发送普通消息先进先出,(,FIFO,)次序,Msg 3,接收任务,等待列表,Msg 2,Msg 1,消息队列,发送紧急消息后进先出,(,LIFO,)次序,发送消息,如果发送消息时,队列已被填满,,则不同的操作系统可能采取不同的处理办法:,挂起试图向已满的消息队列中发送消息的任务(不适用于中断服务程序),简单地丢弃该条消息并向调用者返回错误信息,广播消息,。在此之前所有试图从队列中接收消息的任务此时都将获得相同的消息。该功能拷贝消息到各任务的消息缓冲中(或者让所有的等待任务得到指向消息的指针),并唤醒所有的等待任务。,接收消息,如果指定的消息队列中有消息,则将其中的第一条消息拷贝到调用者的缓冲区(或者将第一条消息指针传递给调用者),并从消息队列中删除它。,如果此时消息队列中没有消息,则可能出现以下几种情况:,永远等待消息的到达,:等待消息的任务按,FIFO,或优先级高低顺序排列在等待队列中,等待消息且指定等待时限,:等待消息的任务按,FIFO,或优先级高低顺序排列在等待队列中,不等待,强制立即返回,接收消息,限时等待可有效预防死锁,中断服务程序接收消息时必须选择不等待,因为中断服务程序是不能被阻塞的。,如果消息队列被应用删除,则所有等待该消息队列的任务都被返回一个错误信息,并回复到就绪状态。,接收消息,Task 4,High,消息队列,接收任务等待列表,任务等待列表基于,优先级的次序,Task 2,medium,Task 3,medium,Task 1,Low,Task 4,High,消息队列,接收任务等待列表,任务等待列表先进先出,(,FIFO,)次序,Task 2,medium,Task 3,medium,Task 1,Low,删除消息队列,从系统中删除指定的消息队列,释放,消息队列控制块,及,消息队列缓冲区,。,任何知道此消息队列,ID,号的代码都可以删除它。,消息队列被删除后,所有等待从这个消息队列接收消息的任务都回到,就绪态,,并得到一个错误信息表明消息队列已被删除。,消息队列的其他典型使用,紧耦合的单向数据通信:发送任务发送消息后要求一个响应信号,表明接收任务已经成功接收到消息。,Task1,Task2,消息队列的其他典型使用,紧耦合的双向数据通信 :如果数据需要在任务之间双向流动,则可以采用紧耦合的双向数据通信模式(也称为全双工通信)。,Task1,Task2,第三节事 件,概述,事件机制的主要数据结构,典型的事件操作,事件机制的典型应用,在嵌入式实时内核中,事件是指一种表明预先定义的系统事件已经发生的机制。,事件机制用于任务与任务之间、任务与,ISR,之间的同步。其主要的特点是可实现,一对多的同步,。,一个事件就是一个标志,,不具备其它信息。,一个或多个事件构成一个事件集,。事件集可以用一个指定长度的变量(,比如一个,8bit, 16bit,或,32bit,的无符号整型变量,,不同的操作系统其具体实现不一样)来表示,而每个事件由在事件集变量中的某一位来代表。,概述,事件及事件集有以下特点:,事件间相互独立,事件仅用于同步,不提供数据传输功能,事件无队列,即多次发送同一事件,在未经过任何处理的情况下,其效果等同于只发送一次。,提供事件机制的意义在于:,当某任务要与多个任务或中断服务同步时,就需要使用事件机制。,若任务需要与一组事件中的任意一个发生同步,可称为,独立型同步,(逻辑,“或”,关系)。,任务也可以等待若干事件都发生时才同步,称为,关联型同步,(逻辑,“与”,关系)。,概述,“,或,”,同步和,“,与,”,同步,概述,任务,任务,任务,任务,ISR,ISR,OR,AND,“,与”型同步,“,或”型同步,事件集,事件集,POST,POST,PEND,PEND,用多个事件的组合发信号给多个任务,概述,任务,任务,任务,ISR,OR,AND,事件集,事件集,事件集,(,8,,,16,或,32,位),POST,PEND,PEND,术语:,发送事件集,。指在一次发送过程中发往接收者(比如任务)的一个或多个事件的组合。,待处理事件集,。指已被发送到一个接收者但还没有被接收(即正在等待处理)的所有事件的集合。,事件条件,。指事件接收者在一次接收过程中期待接收的一个或多个事件的集合。,“或”同步:待处理事件集只要包括事件条件中的任一事件即可满足要求;,“与”同步:其二是待处理事件集必须包括事件条件中的全部事件方可满足要求,。,概述,事件机制的主要数据结构,事件集控制块:管理所有,创建,的事件集,或者,事件集附属于任务,,不需创建,,其相关参数成为任务控制块的一部分,事件的内部实现机制实例说明,C/OS-II,事件标志组数据结构,OS_FLAG_GRP,typedef struct,INT8UOSFlagType;,/,指示本数据结构的类型,void*OSFlagWaitList;,/,等待事件标志的任务链表,OS_FLAGSOSFlagFlags;,/,各事件标志的当前状态,OS_FLAG_GRP;,事件标志节点数据结构,OS_FLAG_NODE,typedef struct,void*OSFlagNodeNext;,/,后驱指针,void*OSFlagNodePrev;,/,前驱指针,void*OSFlagNodeTCB;,/,任务控制块指针,void*OSFlagNodeFlagGrp;,/,指回,OS_FLAG_GRP,结构,OS_FLAGSOSFlagNodeFlags;,/,所等待的事件标志组合,INT8UOSFlagNodeWaitType;,/,等待类型(与、或),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);,接收事件(集),在接收事件(集)时可以有如下选项,WAIT,NO_WAIT,接收事件(集)时可等待,接收事件(集)时不等待,接收者永远等待,直到事件条件被满足后成功返回;,接收者根据指定的时限等待。,EVENT_ALL,EVENT_ANY,待处理事件集必须包含事件条件中的全部事件方可满足要求,,即按照“与”条件接收事件,待处理事件集只要包含事件条件中的任一事件即可满足要求,,即按照“或”条件接收事件,接收(等待)事件标志组的事件标志位,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,if(flags_rdy=flags),/,事件标志当前状态与等待条件相符,pgrp-OSFlagFlags,/,清除(即,“,消费,”,)满足条件的事件标志,flags_cur=pgrp-OSFlagFlags;,*err=OS_NO_ERR;,return(flags_cur);,/,返回处理后的事件标志组,elseOS_FlagBlock(pgrp, ,/,事件标志当前状态与等待条件不相符,任务被阻塞,break;,接收(等待)事件标志组的事件标志位,OSFlagPend(),case OS_FLAG_WAIT_SET_ANY:,/,任务以,“,或,”,方式等待事件标志,flags_rdy=pgrp-OSFlagFlags,if(flags_rdy!=(OS_FLAGS)0),/,有满足条件的事件标志,pgrp-OSFlagFlags,/,清除(即,“,消费,”,)满足条件的事件标志,flags_cur=pgrp-OSFlagFlags;,*err=OS_NO_ERR;,return(flags_cur);,/,返回处理后的事件标志组,elseOS_FlagBlock(pgrp, ,/,事件标志当前状态与等待条件不相符,任务被阻塞,break;,default:,flags_cur=(OS_FLAGS)0;,*err=OS_FLAG_ERR_WAIT_TYPE;,return(flags_cur);,OS_Sched();,/,当前任务被放到事件标志等待链后,内核实施任务调度,if(OSTCBCur-OSTCBStat & OS_STAT_FLAG),/,判断任务重新就绪的原因,如果是等待超时,OS_FlagUnlink(,/,将任务从事件标志等待链中解除下来,OSTCBCur-OSTCBStat=OS_STAT_RDY;,/,设置当前任务状态为就绪,flags_cur=(OS_FLAGS)0;,/,无效的事件标志状态,*,err=OS_TIMEOUT;,/,超时信号,else,/,任务重新就绪的原因是在限定时间得到了满足条件的事件标志,pgrp-OSFlagFlags,/,清除(即,“,消费,”,)满足条件的事件标志,flags_cur=pgrp-OSFlagFlags;,*err=OS_NO_ERR;,return(flags_cur);,接收(等待)事件标志组的事件标志位,OSFlagPend(),添加一个任务到事件标志组等待任务链表中,OS_FlagBlock(),OS_FLAG_GRP,OS_EVENT_TYPE_FLAG,AND or OR,AND or OR,0,0,OS_TCB,OS_TCB,OSTCBCur,AND or OR,OS_FLAG_NODE,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 ,if (flags_rdy = flags) pgrp-OSFlagFlags ,/,事件标志当前状态与等待条件相符,清除(即,“,消费,”,)相应的事件标志,else *err = OS_FLAG_ERR_NOT_RDY;,/,不符合条件,返回错误信息,flags_cur = pgrp-OSFlagFlags;,break;,接收(无等待地获取)事件标志,OSFlagAccept(),case OS_FLAG_WAIT_SET_ANY:,/,”,或,”,方式等待,flags_rdy = pgrp-OSFlagFlags ,if (flags_rdy != (OS_FLAGS)0),pgrp-OSFlagFlags ,/,事件标志当前状态与等待条件相符,清除(即,“,消费,”,)相应的事件标志,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);,发送事件(集),调用者(任务或中断)构造一个事件(集),将其发往接收者(比如目标任务)。可能会出现以下几种情况之一:,目标任务正在等待的事件条件得到满足,任务就绪;,目标任务正在等待的事件条件没有得到满足,该事件(集)被按“或”操作,保存到目标任务的待处理事件集中,目标任务继续等待;,目标任务未等待事件(集),该事件(集)被按“或”操作,保存到目标任务的待处理事件集中。,发送(置位)事件标志组中的事件标志,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 ,if (flags_rdy = pnode-OSFlagNodeFlags) ,/,符合等待条件,if (OS_FlagTaskRdy(pnode, flags_rdy) = TRUE),sched = TRUE;,/,如果任务就绪,设置调度标志,break;,case OS_FLAG_WAIT_SET_ANY:,/,”,或,”,方式等待,flags_rdy = pgrp-OSFlagFlags ,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(),删除事件集,回收事件集控制块到空闲链中,等待接收该事件集的任务被恢复就绪,删除事件标志组,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
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 小学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!