第八讲任务同步与通信.ppt

上传人:本田雅阁 文档编号:3165887 上传时间:2019-07-18 格式:PPT 页数:47 大小:336.02KB
返回 下载 相关 举报
第八讲任务同步与通信.ppt_第1页
第1页 / 共47页
第八讲任务同步与通信.ppt_第2页
第2页 / 共47页
第八讲任务同步与通信.ppt_第3页
第3页 / 共47页
第八讲任务同步与通信.ppt_第4页
第4页 / 共47页
第八讲任务同步与通信.ppt_第5页
第5页 / 共47页
点击查看更多>>
资源描述

《第八讲任务同步与通信.ppt》由会员分享,可在线阅读,更多相关《第八讲任务同步与通信.ppt(47页珍藏版)》请在三一文库上搜索。

1、第八讲(4) 任务同步与通信,授课教师:李英祥 电邮地址:,2019/7/18,,2,主要内容,1. 事件控制块ECB 2. 信号量 3. 邮箱 4. 消息队列,2019/7/18,,3,1. 事件控制块ECB,事件控制块ECB 初始化一个ECB块 OSEVENTWAITLISTINIT() 使一个任务进入就绪状态 OSEVENTTASKRDY() 使一个任务进入等待状态 OSEVENTTASKWAIT() 由于等待超时将一个任务置为就绪状态 OSEVENTTO(),2019/7/18,,4,事件控制块ECB,C/OS-II通过定义的OS_EVENT数据结构(事件控制块ECB)来维护一个事件控

2、制块的所有信息; 该结构中除了包含了: 事件本身的定义,如用于信号量的计数器,用于指向邮箱的指针,以及指向消息队列的指针数组等; 等待该事件的所有任务的列表;,2019/7/18,,5,OSEventType定义了事件的具体类型,可以是: 信号量(OS_EVENT_SEM); 邮箱(OS_EVENT_TYPE_MBOX); 或消息队列(OS_EVENT_TYPE_Q)中的一种;,2019/7/18,,6,与任务就绪列表类似!,等待事件任务列表,2019/7/18,,7,事件控制块的总数由用户所需要的信号量、邮箱和消息队列的总数决定; 该值由OS_CFG.H 中的#define OS_MAX_E

3、VENTS定义; 在调用OSInit()时,所有事件控制块被链接成一个单向链表空闲事件控制块链表; 每当建立一个信号量、邮箱或者消息队列时,就从该链表中取出一个空闲事件控制块,并对它进行初始化; 因为信号量、邮箱和消息队列一旦建立就不能删除,所以事件控制块也不能放回到空闲事件控制块链表中;,2019/7/18,,8,2019/7/18,,9,对于事件控制块进行的一些通用操作包括: 初始化一个事件控制块 使一个任务进入就绪态 使一个任务进入等待该事件的状态 因为等待超时而使一个任务进入就绪态 C/OS-II将上面的操作用4个系统函数实现,它们是: OSEventWaitListInit() OS

4、EventTaskRdy() OSEventWait() OSEventTO(),2019/7/18,,10,初始化一个事件控制块OSEventWaitListInit(),当建立一个信号量、邮箱或者消息队列时,相应的建立函数OSSemCreate(),OSMboxCreate(),或者OSQCreate()通过调用OSEventWaitListInit()对事件控制块中的等待任务列表进行初始化; 该函数的调用参数只有一个,就是指向需要初始化的事件控制块的指针pevent。,2019/7/18,,11,使一个任务进入就绪态OSEventTaskRdy(),当发生了某个事件,该事件对应的OSSe

5、mPost(),OSMboxPost(),OSQPost(),和OSQPostFront()函数调用OSEventTaskRdy(); 该函数从等待任务队列中删除HPT任务(Highest Priority Task),并把该任务置于就绪态;,2019/7/18,,12,使一个任务进入等待某事件发生状态 OSEventTaskWait(),当某个任务要等待一个事件的发生时,相应事件的OSSemPend(),OSMboxPend()或者OSQPend()函数会调用该函数OSEventTaskWait(); 该函数将当前任务从就绪任务表中删除,并放到相应事件的事件控制块的等待任务表中;,2019/

6、7/18,,13,等待超时而将任务置为就绪态 OSEventTO(),当在预先指定的时间内任务等待的事件没有发生时,OSTimeTick()函数会因为等待超时而将任务的状态置为就绪; 在这种情况下,事件的OSSemPend(),OSMboxPend()或者OSQPend()函数会调用OSEventTO()来完成这项工作; 该函数负责从事件控制块中的等待任务列表里将任务删除,并把它置成就绪状态;,2019/7/18,,14,信号量 建立信号量OSSemCreate() 等待信号量 OSSemPend() 发送信号量 OSSemPost() 无等待地请求信号量 OSSemAccept() 查询信号

7、量的当前状态 OSSemQuery(),2. 信号量,2019/7/18,,15,C/OS-II中的信号量由两部分组成:一个是信号量的计数值,它是一个16位的无符号整数(0 到65,535之间);另一个是由等待该信号量的任务组成的等待任务表 ; 如果信号量是用于对共享资源的访问,那么该信号量的初始值应设为1(例如,把它当作二值信号量使用)。最后,如果该信号量是用来表示允许任务访问n个相同的资源,那么该初始值显然应该是n,并把该信号量作为一个可计数的信号量使用;,2019/7/18,,16,C/OS-II提供了5个对信号量进行操作的函数:OSSemCreate(),OSSemPend(),OSS

8、emPost(),OSSemAccept()和OSSemQuery(),2019/7/18,,17,建立信号量OSSemCreate(),OSSemCreate()函数建立并初始化一个信号量。信号量的作用如下: 允许一个任务和其他任务或者中断同步 取得设备的使用权 标志事件的发生 参数 value 参数是建立的信号量的初始值,可以取0到65535之间的任何值。 返回值 OSSemCreate()返回给调用函数一个指向任务控制块的指针。 如果没有可用的事件控制块,OSSemCreate()函数返回空指针。,2019/7/18,,18,等待信号量 OSSemPend(),OSSemPend()函数

9、用于任务试图取得设备的使用权。 如果任务调用OSSemPend()函数时,信号量的值大于零,OSSemPend()函数递减该值并返回该值。如果调用时信号量等于零,OSSemPend()函数将任务加入该信号量的等待队列。OSSemPend()函数挂起当前任务直到其他的任务或中断置起信号量或超出等待的预期时间。 如果在预期的时钟节拍内信号量被置起,C/OS-默认最高优先级的任务取得信号量恢复执行。一个被OSTaskSuspend()函数挂起的任务也可以接受信号量,但这个任务将一直保持挂起状态直到通过调用OSTaskResume()函数恢复任务的运行。,2019/7/18,,19,参数 pevent

10、 是指向信号量的指针。该指针的值在建立该信号量时可以得到。(参考OSSemCreate()函数)。 Timeout 允许一个任务在经过了指定数目的时钟节拍后还没有得到需要的信号量时恢复运行状态。如果该值为零表示任务将持续的等待信号量。最大的等待时间为65535个时钟节拍。这个时间长度并不是非常严格的,可能存在一个时钟节拍的误差,因为只有在一个时钟节拍结束后才会减少定义的等待超时时钟节拍。 Err 是指向包含错误码的变量的指针。OSSemPend()函数返回的错误码可能为下述几种: OS_NO_ERR :信号量不为零。 OS_TIMEOUT :信号量没有在指定的周期数内置起。 OS_ERR_PE

11、ND_ISR :从中断调用该函数。虽然规定了不允许从中断调用该函数,但C/OS-仍然包含了检测这种情况的功能。 OS_ERR_EVENT_TYPE :pevent 不是指向信号量的指针;,2019/7/18,,20,2019/7/18,,21,发送信号量 OSSemPost(),OSSemPost()函数置起指定的信号量: 如果指定的信号量是零或大于零,OSSemPost()函数递增该信号量并返回。 如果有任何任务在等待信号量,最高优先级的任务将得到信号量并进入就绪状态。 参数 pevent 是指向信号量的指针。该指针的值在建立该信号量时可以得到。 返回值 OSSemPost()函数的返回值为

12、下述之一: OS_NO_ERR :信号量成功的置起 OS_SEM_OVF :信号量的值溢出 OS_ERR_EVENT_TYPE :pevent 不是指向信号量的指针。,2019/7/18,,22,无等待地请求信号量 OSSemAccept(),当一个任务请求一个信号量时,如果该信号量暂时无效,也可以让该任务简单地返回,而不是进入睡眠等待状态,这种情况下的操作是由OSSemAccept()函数完成的 ; 参数 pevent 是指向需要查询的设备的信号量; 返回值 当调用OSSemAccept()函数时,设备信号量的值大于零,说明设备就绪,这个值被返回调用者,设备信号量的值减一; 当调用OSSem

13、Accept()函数时,设备信号量的值等于零,说明设备没有就绪,返回零;,2019/7/18,,23,查询信号量的当前状态 OSSemQuery(),OSSemQuery()函数用于获取某个信号量的信息:可以得知是否有,以及有多少任务位于信号量的任务等待队列中; 使用OSSemQuery()之前,应用程序需要先创立类型为OS_SEM_DATA的数据结构,用来保存从信号量的事件控制块中取得的数据; 参数 pevent是一个指向信号量的指针。该指针在信号量建立后返回调用程序; Pdata是一个指向数据结构OS_SEM_DATA的指针; 返回值 OSSemQuery()函数有下述两个返回值: OS_

14、NO_ERR 表示调用成功。 OS_ERR_EVENT_TYPE 表示未向信号量传递指针。,2019/7/18,,24,2. 邮箱,邮箱 建立一个邮箱OSMboxCreate() 等待一个邮箱中的消息OSMboxPend() 发送一个消息到邮箱中OSMboxPost() 无等待地从邮箱中得到一个消息OSMboxAccept() 查询一个邮箱的状态OSMboxQuery(),2019/7/18,,25,邮箱,邮箱是C/OS-II中另一种通讯机制; 它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量; 该指针指向一个包含了特定“消息”的数据结构; C/OS-II提供了5种对邮箱的操

15、作: OSMboxCreate() OSMboxPend() OSMboxPost() OSMboxAccept() OSMboxQuery(),2019/7/18,,26,建立一个邮箱OSMboxCreate(),OSMboxCreate()建立并初始化一个消息邮箱,消息邮箱允许任务或中断向其他一个或几个任务发送消息 参数 msg 参数用来初始化建立的消息邮箱。如果该指针不为空,建立的消息邮箱将含有消息。 返回值 指向分配给所建立的消息邮箱的事件控制块的指针。如果没有可用的事件控制块,返回空指针。,2019/7/18,,27,2019/7/18,,28,2019/7/18,,29,等待一个邮

16、箱中的消息OSMboxPend(),OSMboxPend()用于任务等待消息。消息通过中断或另外的任务发送给需要的任务。消息是一个以指针定义的变量,在不同的程序中消息的使用也可能不同。如果调用OSMboxPend()函数时消息邮箱已经存在需要的消息,那么该消息被返回给OSMboxPend()的调用者,消息邮箱中清除该消息。如果调用OSMboxPend()函数时消息邮箱中没有需要的消息,OSMboxPend()函数挂起当前任务直到得到需要的消息或超出定义等待超时的时间。如果同时有多个任务等待同一个消息,C/OS-默认最高优先级的任务取得消息并且任务恢复执行。一个由OSTaskSuspend()函

17、数挂起的任务也可以接受消息,但这个任务将一直保持挂起状态直到通过调用OSTaskResume()函数恢复任务的运行。,2019/7/18,,30,参数 pevent 是指向即将接受消息的消息邮箱的指针。该指针的值在建立该消息邮箱时可以得到; Timeout 允许一个任务在经过了指定数目的时钟节拍后还没有得到需要的消息时恢复运行。如果该值为零表示任务将持续的等待消息; Err 是指向包含错误码的变量的指针; 返回值 OSMboxPend()函数返回接受的消息并将 *err置为OS_NO_ERR; 如果在指定数目的时钟节拍内没有接受到需要的消息,OSMboxPend()函数返回空指针并且将 *er

18、r设置为OS_TIMEOUT。,2019/7/18,,31,发送一个消息到邮箱中OSMboxPost(),OSMboxPost()函数通过消息邮箱向任务发送消息。如果消息邮箱中已经存在消息,返回错误码说明消息邮箱已满。OSMboxPost()函数立即返回调用者,消息也没有能够发到消息邮箱。如果有多个任务在等待消息邮箱的消息,最高优先级的任务将得到这个消息。 参数 pevent 是指向即将接受消息的消息邮箱的指针。 Msg 是即将实际发送给任务的消息。消息是一个指针长度的变量,在不同的程序中消息的使用也可能不同。不允许传递一个空指针,因为这意味着消息邮箱为空。 返回值 OS_NO_ERR :消息

19、成功的放到消息邮箱中。 OS_MBOX_FULL :消息邮箱已经包含了其他消息,不空。 OS_ERR_EVENT_TYPE :pevent 不是指向消息邮箱的指针。,2019/7/18,,32,无等待地从邮箱中得到一个消息OSMboxAccept(),OSMboxAccept()函数查看指定的消息邮箱是否有需要的消息。不同于OSMboxPend()函数,如果没有需要的消息,OSMboxAccept()函数并不挂起任务。如果消息已经到达,该消息被传递到用户任务并且从消息邮箱中清除。参数 pevent 是指向需要查看的消息邮箱的指针。 返回值 如果消息已经到达,返回指向该消息的指针;如果消息邮箱没

20、有消息,返回空指针。,2019/7/18,,33,查询一个邮箱的状态OSMboxQuery(),OS_MBOX.C任务或中断OS_MBOX_ENOSMboxQuery()函数用来取得消息邮箱的信息。用户程序必须分配一个OS_MBOX_DATA的数据结构,该结构用来从消息邮箱的事件控制块接受数据。 通过调用OSMboxQuery()函数可以知道任务是否在等待消息以及有多少个任务在等待消息,还可以检查消息邮箱现在的消息。 参数 pevent 是指向即将接受消息的消息邮箱的指针。 Pdata 是指向OS_MBOX_DATA数据结构的指针,该数据结构包含下述成员: Void *OSMsg; /* 消息

21、邮箱中消息的复制 */ INT8U OSEventTblOS_EVENT_TBL_SIZE; /*消息邮箱等待队列的复制*/ INT8U OSEventGrp; 返回值 OS_NO_ERR :调用成功 OS_ERR_EVENT_TYPE :pevent 不是指向消息邮箱的指针。,2019/7/18,,34,3.消息队列,消息队列 建立一个消息队列OSQCreate() 等待一个消息队列中的消息OSQPend() 向消息队列发送一个消息(FIFO)OSQPost() 向消息队列发送一个消息(LIFO)OSQPostFront() 无等待地从一个消息队列中取得消息 OSQAccept() 清空一个

22、消息队列 OSQFlush() 查询一个消息队列的状态OSQQuery(),2019/7/18,,35,消息队列,消息队列是C/OS-II中的一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送以指针方式定义的变量。 C/OS-II提供了7个对消息队列进行操作的函数:OSQCreate(),OSQPend(),OSQPost(),OSQPostFront(),OSQAccept(),OSQFlush()和OSQQuery()函数。,2019/7/18,,36,2019/7/18,,37,实际上,我们可以将消息队列看作时多个邮箱组成的数组,只是它们共用一个等待任务列表。每个指针所指向

23、的数据结构是由具体的应用程序决定的。N代表了消息队列中的总单元数。,2019/7/18,,38,2019/7/18,,39,C/OS-II在初始化时建立一个空闲的队列控制块链表,如图 F6.9所示。,2019/7/18,,40,建立一个消息队列OSQCreate(),OSQCreate()函数建立一个消息队列。任务或中断可以通过消息队列向其他一个或多个任务发送消息。消息的含义是和具体的应用密切相关的。 参数 start 是消息内存区的基地址,消息内存区是一个指针数组。 Size 是消息内存区的大小。 返回值 返回一个指向消息队列事件控制块的指针。如果没有空余的事件空闲块,返回空指针。,2019

24、/7/18,,41,等待一个消息队列中的消息OSQPend(),OSQPend()函数用于任务等待消息。 如果调用OSQPend()函数时队列中已经存在需要的消息,那么该消息被返回给OSQPend()函数的调用者,队列中清除该消息。 如果调用OSQPend()函数时队列中没有需要的消息,OSQPend()函数挂起当前任务直到得到需要的消息或超出定义的超时时间。 如果同时有多个任务等待同一个消息,C/OS-默认最高优先级的任务取得消息并且任务恢复执行。 一个由OSTaskSuspend()函数挂起的任务也可以接受消息,但这个任务将一直保持挂起状态直到通过调用OSTaskResume()函数恢复任

25、务的运行。,2019/7/18,,42,参数 pevent 是指向即将接受消息的队列的指针。该指针的值在建立该队列时可以得到。 Timeout 允许一个任务在经过了指定数目的时钟节拍后还没有得到需要的消息时恢复运行状态。如果该值为零表示任务将持续的等待消息。 Err 是指向包含错误码的变量的指针。OSQPend()函数返回的错误码可能为下述几种: OS_NO_ERR :消息被正确的接受。 OS_TIMEOUT :消息没有在指定的周期数内送到。 OS_ERR_PEND_ISR :从中断调用该函数。虽然规定了不允许从中断调用该函数,但C/OS-仍然包含了检测这种情况的功能。 OS_ERR_EVEN

26、T_TYPE :pevent 不是指向消息队列的指针。 返回值 OSQPend()返回接受的消息并将 *err置为OS_NO_ERR。如果没有在指定数目的时钟节拍内接受到需要的消息,返回空指针并且将 *err设置为OS_TIMEOUT。,2019/7/18,,43,向消息队列发送一个消息(FIFO)OSQPost(),OSQPost()函数通过消息队列向任务发送消息。 如果队列中已经存满消息,返回错误码。OSQPost()函数立即返回调用者,消息也没有能够发到队列。 如果有任何任务在等待队列中的消息,最高优先级的任务将得到这个消息。 如果等待消息的任务优先级比发送消息的任务优先级高,那么高优先

27、级的任务将得到消息而恢复执行,也就是说,发生了一次任务切换。 消息队列是先入先出(FIFO)机制的,先进入队列的消息先被传递给任务。 参数 pevent 是指向即将接受消息的消息队列的指针。 Msg 是即将实际发送给任务的消息。 返回值 OS_NO_ERR :消息成功的放到消息队列中。 OS_MBOX_FULL :消息队列已满。 OS_ERR_EVENT_TYPE :pevent 不是指向消息队列的指针。,2019/7/18,,44,向消息队列发送一个消息(LIFO)OSQPostFront(),OSQPostFront()函数通过消息队列向任务发送消息。 OSQPostFront()函数和O

28、SQPost()函数非常相似,不同之处在于OSQPostFront()函数将发送的消息插到消息队列的最前端。 也就是说,OSQPostFront()函数使得消息队列按照后入先出(LIFO)的方式工作,而不是先入先出(FIFO)。,2019/7/18,,45,无等待地从一个消息队列中取得消息 OSQAccept(),OSQAccept()函数检查消息队列中是否已经有需要的消息。 不同于OSQPend()函数,如果没有需要的消息,OSQAccept()函数并不挂起任务。如果消息已经到达,该消息被传递到用户任务。 参数 pevent 是指向需要查看的消息队列的指针。 返回值 如果消息已经到达,返回指

29、向该消息的指针;如果消息队列没有消息,返回空指针。,2019/7/18,,46,清空一个消息队列 OSQFlush(),OSQFlush()函数清空消息队列并且忽略发送往队列的所有消息。不管队列中是否有消息,这个函数的执行时间都是相同的。 参数 pevent 是指向消息队列的指针。 返回值 OS_NO_ERR :消息队列被成功清空 OS_ERR_EVENT_TYPE :试图清除不是消息队列的对象,2019/7/18,,47,查询一个消息队列的状态OSQQuery(),OSQQuery()函数用来取得消息队列的信息。用户程序必须建立一个OS_Q_DATA的数据结构,用来保存从消息队列的事件控制块得到的数据。 通过调用OSQQuery()函数可以知道任务是否在等待消息、有多少个任务在等待消息、队列中有多少消息以及消息队列可以容纳的消息数。 参数 pevent 是指向即将接受消息的消息邮箱的指针。该指针的值在建立该消息邮箱时可以得到。(参考OSQCreate()函数)。 Pdata 是指向OS_Q_DATA数据结构的指针; 返回值 OS_NO_ERR :调用成功 OS_ERR_EVENT_TYPE :pevent 不是指向消息队列的指针。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1