新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > ucOS- II中设计了五种通讯机制

ucOS- II中设计了五种通讯机制

作者:时间:2016-11-27来源:网络收藏
4.2.4 OSMboxPost:往邮箱发送消息: 首先检查是否有任务正在等待邮箱消息的到来,如果有的话就通过OS_EventTaskRdy找到优先级最高的任务,然后重新调度,注意,这时候要发送的消息会放到优先级最高任务的TCB中!如果没有任务在等待该邮箱消息的到来,就直接把消息放到邮箱中。
5 队列的实现
队列的实现类似于邮箱,也是用来从一个任务向其他任务发送消息,不过,队列更为复杂,之所以称之为队列,它可以发送多个消息,可以把邮箱看成是只发送一个消息的队列。
5.1 数据结构的设计:
由于队列可以发送多个消息,所以仅仅用ECB不能满足要求,于是作者引入了另外一个数据结构QS_Q,用来描述队列代表的多个消息,但是这里与 邮箱不同的是,QS_Q本身并不包含消息本身,而是队列代表的一系列消息的描述。当然,真正的消息放在一个系统的消息缓冲区MsgTbl,这个缓冲区是预 先定义好的,其大小根据实际的应用而定制。所以对于队列来说,用到三个数据结构,ECB, QS_Q, MsgTbl,其中ECB和QS_Q是每个队列都有一个,而MsgTbl是系统中所有队列共享的!
QS_Q由ECB的变量OSEventPtr引出,ECB的OSEventCnt没有用到,其他的变量用法同信号量。对于QS_Q来说,和ECB一样是从系统QS_Q缓冲区中申请的。
5.2 核心函数为五个,其中四个类似于前面的信号量,互斥体和邮箱,此外还多了一个清空队列的函数:
5.2.1 OSQCreate:创建一个队列:首先申请一个ECB,然后申请一个QS_Q,最后初始化申请到的ECB和QS_Q,其中用到OS_EventWaitListInit初始化等待任务表。
5.2.2 OSQDel:删除一个队列:实现和信号量的OSSemDel基本一样,不同的是,由于队列引入了QS_Q,必须加归还申请到的QS_Q到系统QS_Q缓冲区的操作。
5.2.3 OSQPend:等待一个消息:注意这个函数只是等待一个消息,而这个消息是不是想要的它并不知道!首 先通过QS_Q判断该队列是不是有消息,如果有的话更新QS_Q然后返回;如果该队列没有消息,那么更新当前任务的TCB以表明当前任务正在等待该队列的 消息,然后通过OS_EventTaskWait挂起当前任务,然后重新调度——OS_Sched!这个时候当前任务会等到消息到来或者超时才会得以继续 执行。。。当继续执行的时候,判断是得到消息才执行,还是超时,如果是前者的话,直接更新当前任务的TCB;如果是后者的话,通过OS_EventTO更 新状态。
5.2.4 OSQPost:发送一个消息:这个函数放一个消息到队列。首先检查是不是有任务在等待该队列的消息,如果有的话,就通过OS_EventTaskRdy 找到正在等待该队列消息的任务中优先级最高的那个,然后重新调度——OS_Sched!如果没有的话,更新该队列的QS_Q,也就是加一个消息进该队列。
5.2.5 OSQFlush:刷新该队列,其实就是简单的重置QS_Q,系统消息缓冲区MsgTbl是不需要改动的!
前面对信号量,互斥体,邮箱,队列做了一个简单的总结,这四个通讯机制的核心都是ECB,而这里总结的事件组(evnet flag),作者没有用ECB,而是重新设计了两个单独的数据结构来实现。下面对事件组这最复杂的通讯机制做一总结,呵呵
6 事件组
事件组的用途主要是把多个事件和多个任务能够联系起来,使通讯机制更加灵活,它有两部分组成:一是表示了各个事件的状态;二是等待这些事件的任务列表。
6.1 数据结构设计:
如上面提到的,事件组用到了全新的两个数据结构:OS_FLAG_GRP和OS_FLAG_NODE——OS_FLAG_GRP有三个变 量:OSFlagType(和ECB中的OSEventType一样,用来标识这是一个事件组),OSFlagWaitList(负责引出等待事件组的任 务列表)和OSFlagFlags(标识当前事件状态);OS_FLAG_NODE有六个变量:OSFlagNodeNext和 OSFlagNodePrev(用来将OS_FLAG_NODE构成双向列表),OSFlagNodeTCB(正在等待事件组的任务 TCB),OSFlagNodeFlagGrp(该变量反向指到OS_FLAG_GRP,用来记录事件组),OSFlagNodeFlags(标识任务和 该节点关联的任务正在等待的事件标志)和OSFlagNodeWaitType(标识该节点相关联任务正在等待的方式:是全部等到,还是只等其中一个)。 从上面不难看出,OS_FLAG_GRP其实相当于ECB中的除了等待任务表的其他三个变量,而OS_FLAG_NODE相当于等待任务表,不同的是,由 于等待的任务不是仅仅等待一个事件,而是等待一系列事件,这样,等待任务表就不能胜任了——因为等待任务表只能标明哪些个任务正在等待,但是等待的目标是 唯一的,而这里等待的目标可能会是多个!
6.2 核心功能函数:
由于用到了不同的数据结构,OS_EventWaitListInit,OS_EventTaskRdy,OS_EventTaskWait和 OS_EventTO就必须重新设计,作者在这里设计了另外的核心功能函数,OS_FlagBlock,OS_FlagRdy和 OS_FlagUnlink。
6.2.1 OS_FlagBlock:其作用相当于OS_EventTaskWait:将当前任务从就绪任务表中移走,更新当前任务的TCB,不同的是,在 OS_EventTaskWait中将当前任务加入等待任务表,而这里由于没有用到等待任务表,而是创建一个OS_FLAG_NODE,换句话说,只要有 OS_FLAG_NODE就表明有任务在等待事件组,其实原理上和等待任务表是一样的。
6.2.2 OS_FlagRdy:其作用相当于OS_FlagTaskRdy:将OS_FLAG_NODE所指向的任务的TCB更新以表明等到了事件组,如果该任务 不在等待其他的目标,将其加入就绪任务表中。然后用OS_FlagUnlink将此任务的OS_FLAG_NODE删除。
6.2.3 OS_FlagUnlink:该函数主要是把特定的OS_FLAG_NODE从等待任务列表中删除。
6.3 核心函数和信号量类似,有四个,其实现比较简单:
6.3.1 OSFlagCreate: 创建一个事件组:从系统事件组缓冲区中申请一个OS_FLAG_GRP,然后初始化该OS_FLAG_GRP。
6.3.2 OSFlagDel:删除一个事件组:和信号量的OSSemDel几乎完全一样,不同的是用OS_FlagRdy而不是OS_EventTaskRdy。
6.3.3 OSFlagPend:等待一个事件组:这里的等待有两种情况:等待所有的事件到来,等待任何一个事件到来。不管哪种情况,都是先判断需要的标识是不是已 经到来,如果到来的话就更新事件组,然后返回;如果没有到来的话,就会用OS_FlagBlock为当前任务产生一个OS_FLAG_NODE,并将其加 进双向链表里。
6.3.4 OSFlagPost:标识一个事件组一些标识已经到来:先更新OS_FLAG_GRP,然后遍历OS_FLAG_NODE的双向链表,用OS_FlagRdy使那些正在等待这些标识的任务不再等待。
7 各种通讯机制的比较
综合以上五种通讯机制可以看出:信号量是最普通的通讯机制,当需要一般的同步或者资源保护的话,用信号量就可以了;互斥体主要用来解决优先级反 转的问题,当需要在任务间同步资源的时候,用互斥体;邮箱主要用来将一个消息从一个任务发送到另一个任务;队列可以看作是扩展的邮箱,队列可以发送多个消 息;事件组是最复杂的一个通许机制,但最灵活,可以在任务间用多个事件标识来同步,因此用起来需要特别注意!

上一页 1 2 下一页

关键词: ucOS-I通讯机

评论


相关推荐

技术专区

关闭