μC/OS―III对信号量的改进
摘要:μC/OS-III是对μC/OS-II的重大改进,增加了许多新的特性。在信号量的使用上,μC/OS—III增加了一些可选的参数,提高了使用的灵活性;新增了任务内嵌的信号量,可以更高效地和任务进行通信。本文分析对比μC/OS—II和μC/OS—III中信号量内部结构的差异及新增的特性。
关键词:μC/OS—III;信号量;实时操作系统
引言
μC/OS是一个基于优先级调度的可剥夺型实时多任务内核。在多任务的实时内核中,信号量是常用的机制,可以用来实现对共享资源的访问、任务之间的通信和同步,以及任务和中断的同步等功能。μC/OS—II中提供了等待和释放信号量等最基本的服务,而在μC/OS—III中,对信号量的使用增加了一些可选的模式,如非阻塞等待、释放但不进行任务调度等,提高了使用的灵活性。更重要的是,在μC/OS—III中还新增了任务内嵌的信号量,用户程序无需建立信号量便可和任务直接通信,比普通信号量更加简单高效。本文将分析对比μC/OS—II和μC/OS—III中信号量内部结构的差异以及μC/OS—III新增的特性。
1 μC/OS—II中信号量内部结构
在μC/OS—II中,信号量直接使用内核的数据结构OS EVENT,其内部结构如下:
其中,和信号量相关的最重要的就是OSEventCnt、OSEventGrp和OSEventTbl[]。OSEventCnt记录的是信号量的有效值。OSEventTbl[]是一个位映射表,以64级优先级为例,OSEventTbl[]将是一个8×8的位映射表,如果某优先级下有任务在等待该事件,则OSEventTbl[]中对应的位将被置1。为了加快查询过程,又将64级优先级分为8组,用一个8位的整型OSEventGrp来记录每一组的状态。可见,OSEventGrp和OSEve ntTbl[]跟就绪表中的OSRdyGrp和OSRdyTbl[]结构是一模一样的,区别仅仅在于前者记录的是等待该事件的任务的状态,而后者记录的是系统中就绪的任务的状态。而两者的查找过程是一样的,都是通过“掩码表”来快速得到列表中优先级最高的任务。
μC/OS—II提供的信号量相关的最常用的几个API函数如下:
在使用信号量前必须先新建一个信号量,并指定其初始值。当信号量用于对共享资源的访问时,该值应初始化为实际可用的共享资源数;当信号量用来实现任务的同步,则初始值应设为0。调用等待信号量的OSSemPend()函数时可以指定超时选项timeout,在指定的时间内如果没有获得信号量则任务会超时返回。释放信号量时,如果有任务在等待,内核会通过查找OSEventGrp和OSEventTbl[]获得等待任务中优先级最高的任务,该任务将获得信号量从而转入就绪态,内核会进行任务调度。如果获得信号量的任务比正在执行的任务优先级还高,则会进行任务切换。
2 μC/OS-Ⅲ中信号量内部结构
在μC/OS—III中,信号量类型的结构有所变化,并没有和μC/OS—II一样继续采用和“就绪表”类似的结构,而是采用一个“等待列表”的数据结构来记录等待信号量的任务。其数据结构如下:
从上述结构可以看出,μC/OS—III的信号量结构中新增了一个时间戳TS,用来记录最近一次释放信号量(或者是取消等待、删除信号量)的时间。而等待信号量的任务列表则通过一个新的数据结构OS_PEND_LIST来记录,如图1所示。
评论