μC/OS-III_任务挂起表


当一个任务等待信号量、互斥型信号量、时间标志组或消息队列时,该任务就被放入任务挂起表或等待表中,带有任务挂起表的内核对象如下:

相关内容内核对象
信号量、互斥信号量OS_SEM、OS_MUTEX
信号量、事件标志组OS_SEM、OS_FLG_GRP
消息队列OS_Q

1 内核对象数据结构

每种内核对象的头部都包含三个相同的数据域,第一个数据域为内核对象的类型,系统通过该数据域判断内核对象的类型
在这里插入图片描述

内核对象Type数据域的值(4个ASCII值)
信号量SEMA
互斥信号量MUTX
事件标志组FLAG
消息队列QUEU

2 任务挂起表结构

struct  os_pend_list {
    OS_PEND_DATA        *HeadPtr;		/*等待表中的第一个任务(优先级最高)*/
    OS_PEND_DATA        *TailPtr;		/*等待表中的最后一个任务(优先级最低)*/
    OS_OBJ_QTY           NbrEntries;	/*等待表中的表项数目,每一个表象指向一个正在等待内核对象的任务*/
};

任务挂起表实际上不直接指向任务的控制块,而是指向一个OS_PEND_DATA类型的数据结构,该类型的数据结构会在任务被放入任务挂起表时动态地分配到该任务的堆栈空间中。

struct  os_pend_data {
    OS_PEND_DATA        *PrevPtr;				/*等待该内核对象的更高或相同优先级的任务*/
    OS_PEND_DATA        *NextPtr;				/*等待该内核对象的更低或相同优先级的任务*/
    OS_TCB              *TCBPtr;				/*该内核对象的任务的控制块OS_TCB*/
    OS_PEND_OBJ         *PendObjPtr;			/*指向任务正在等待的内核对象*/
    OS_PEND_OBJ         *RdyObjPtr;				/*指向已经准备就绪的内核对象*/
    void                *RdyMsgPtr;				/*指向通过OSQPost()函数发布的信息*/
    OS_MSG_SIZE          RdyMsgSize;			/*通过OSQPost()函数发布信息的大小*/
    CPU_TS               RdyTS;					/*时间戳,记录内核对象被释放(Post)的时刻*/
};

μC/OS-III仅仅允许任务同时等待多个信号量和(或)多个消息队列,不支持同时等待多个事件标志组或互斥信号量。

3 两个任务等待同一个信号量

在这里插入图片描述

struct  os_sem {
    OS_OBJ_TYPE          Type; 			/*被定义为SEMA*/                           
    CPU_CHAR            *NamePtr;       /*信号的名字(ASCII字符串)*/                     
    OS_PEND_LIST         PendList;      /*该信号量的任务挂起表*/                                     
    OS_SEM              *DbgPrevPtr;
    OS_SEM              *DbgNextPtr;
    CPU_CHAR            *DbgNamePtr;
    OS_SEM_CTR           Ctr;			/*信号量的当前值*/
    CPU_TS               TS;			/*时间戳*/
    CPU_INT08U           SemID;   		/*信号量唯一ID号*/
};
  1. OS_PEND_LIST结构体中pendlist->NbrEntries表明有多少个任务正在等待该信号量,pendlist->HeadPtr指向等待该信号量的最高优先级任务(即OS_PEND_DATA结构体),pendlist->TailPtr指向等待该信号量的最低优先级任务(即OS_PEND_DATA结构体)
  2. 每个OS_PEND_DATA结构体都指向其对应的任务控制块TCB,因此可以通过信号量的任务挂起表知道哪个任务在等待该信号量
  3. 每个任务控制块中的OS_TCB.PendDataTblPtr又指回到OS_PEND_DATA结构体(此处指向的可能是一个结构体数组,表征该任务正在同时等待多个内核对象,每一个表项表明一个等待的内核对象)
  4. OS_PEND_DATA结构体构成一个双向链表,系统可以很容易的添加或删除挂起表中的任意一个任务

4 任务同时等待多个内核对象

μC/OS-III仅仅允许任务同时等待多个信号量和(或)多个消息队列,不支持同时等待多个事件标志组或互斥信号量。
在这里插入图片描述
一个任务调用OSPendMulti()来等待多个内核对象,同时指定一个超时时间,该时间对任务等待的内核对象都有效,如果在指定的超时时限内,没有对象被发布,该任务将返回一个错误代码,表示等待超时。

OS_OBJ_QTY  OSPendMulti (OS_PEND_DATA  *p_pend_data_tbl,	/*等待多个内核对象的OS_PEND_DATA结构体数组,结构体中.PendObjPtr表明任务等待的内核对象*/
                         OS_OBJ_QTY     tbl_size,			/*等待内核对象的数目,即OS_PEND_DATA结构体数组的大小*/
                         OS_TICK        timeout,			/*等待超时时间*/
                         OS_OPT         opt,				/*等待对象选项*/
                         OS_ERR        *p_err)				/*返回错误码*/
                         
//例如:一个任务等待3个信号量,2个消息队列
OS_SEM	MySem1;
OS_SEM	MySem2;
OS_SEM	MySem3;
OS_Q	MyQ1;
OS_Q	MyQ2;

void MyTask(void)
{
	OS_ERR	err;
	OS_PEND_DATA	my_pend_multi_tbl[5];
	...
	while(DEF_ON)
	{
		my_pend_multi_tbl[0].PendObjPtr = (OS_PEND_OBJ)&MySem1;
		my_pend_multi_tbl[1].PendObjPtr = (OS_PEND_OBJ)&MySem2;
		my_pend_multi_tbl[2].PendObjPtr = (OS_PEND_OBJ)&MySem3;
		my_pend_multi_tbl[3].PendObjPtr = (OS_PEND_OBJ)&MyQ1;
		my_pend_multi_tbl[4].PendObjPtr = (OS_PEND_OBJ)&MyQ2;
		OSPendMulti((OS_PEND_DATA*)	&my_pend_multi_tbl[0],
					(OS_OBJ_QTY)	5,
					(OS_TICK)		0,
					(OS_OPT)		OS_OPT_PEND_BLOCKING,		/*阻塞等待*/
					(OS_ERR*)		&err);
		/*Check err*/
		...
	}
}

当被调用时,OSPendMulti()函数首先验证OS_PEND_DATA表中指定的所有对象是否为OS_SEM或OS_Q,如果不是则返回错误码。之后函数遍历OS_PEND_DATA表中的所有对象以确定是否有任何一个对象已经被发布,如果有,OSPendMulti()就会根据情况填充表中的.RdyObjPtr、.RdyMsgPtr、RdyMsySize和.RdyTS成员。

4.1 一个任务同时等待多个信号量

在这里插入图片描述

  1. 一个指向OS_PEND_DATA表基地址的指针被放到同时等待两个信号量的任务的控制块中即OS_TCB.PendDataTblPtr
  2. OS_PEND_DATA表的表项数也被放在该任务的控制块中(即OS_TCB.PendDataTblEntries),表明该任务同时等待几个内核对象
  3. 第一个信号量指向OS_PEND_DATA表的第一个表项
  4. OS_PEND_DATA表的第一个表项数据OS_PEND_DATA[0].PendObjPtr指向等待的第一个信号量
  5. 由于第一个信号量只有一个任务在等待,所以OS_PEND_DATA[0]中的PrevPtr和NextPtr都指向NULL
  6. 第二个信号量的具体指向同第一个信号量
4.2 多个任务同时等待多个信号量

在这里插入图片描述
多个任务同时等待多个信号量时,OS_PEND_DATA表被串联起来,位于双向链表前面的OS_PEND_DATA结构体属于高优先级,后面的属于低优先级。当一个任务等待多个内核对象时,OS_PEND_DATA表中只有一个表项的RdyObjPtr为非空值,表明这个任务等待的哪个内核对象被发布。
例如,上面N哪个等待3个信号量,2个消息队列的任务,如果第一个消息队列被发布,则OS_PEND_DATA表中的内容如下图:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值