UCOS的任务管理

  1. 任务控制块及其初始化
  2. $\mu$C/OS-$\amalg$的调度管理
    1. 就绪队列

任务控制块及其初始化

学过操作操作系统的朋友都应该熟悉进程控制块这个概念,这几乎已经成为了我们抽象在操作系统中运行任务的一个统一标准,而这里的任务控制块和进程控制块其实是一个概念。在$\mu$C/OS-$\amalg$中,设计了如下数据结构来对其中运行的任务进行抽象和管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct os_tcb {
OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */

...

struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */
struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */

...

INT32U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event */
INT8U OSTCBStat; /* Task status */
INT8U OSTCBStatPend; /* Task PEND status */
INT8U OSTCBPrio; /* Task priority (0 == highest) */

INT8U OSTCBX; /* Bit position in group corresponding to task priority */
INT8U OSTCBY; /* Index into ready table corresponding to task priority */
OS_PRIO OSTCBBitX; /* Bit mask to access bit position in ready table */
OS_PRIO OSTCBBitY; /* Bit mask to access bit position in ready group */
...
} OS_TCB;

从如上数据结构,我们容易看出,TCB主要描述了如下几方面的信息:

  1. 堆栈
  2. 任务状态
  3. 任务优先级相关

这些信息是任务运行不可或缺的,同时又包含了TCB本身的组织结构和一些其他功能相关的信息。不像在复杂操作系统中那样,任务与任务之间只存在对等关系,不存在父子,兄弟等复杂的关系,而且功能复杂度也简单的多,因此在$\mu$C/OS-$\amalg$的TCB结构相对复杂操作系统的PCB来说简单得多。

TCP的链式组织形式

对于任务控制块的初始化函数如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
INT8U OS_TCBInit (INT8U    prio,     
OS_STK *ptos,
OS_STK *pbos,
INT16U id,
INT32U stk_size,
void *pext,
INT16U opt)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
#if OS_TASK_REG_TBL_SIZE > 0u
INT8U i;
#endif
#if OS_TASK_CREATE_EXT_EN > 0u
#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
INT8U j;
#endif
#endif



OS_ENTER_CRITICAL();
ptcb = OSTCBFreeList; (1)
if (ptcb != (OS_TCB *)0) { (2)
OSTCBFreeList = ptcb->OSTCBNext;
OS_EXIT_CRITICAL();
ptcb->OSTCBStkPtr = ptos; (3)
ptcb->OSTCBPrio = (INT8U)prio;
ptcb->OSTCBStat = OS_STAT_RDY;
ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
ptcb->OSTCBDly = 0;
#if OS_TASK_CREATE_EXT_EN > 0u
ptcb->OSTCBExtPtr = pext; (4)
ptcb->OSTCBStkSize = stk_size;
ptcb->OSTCBStkBottom = pbos;
ptcb->OSTCBOpt = opt;
ptcb->OSTCBId = id;
#else
pext = pext;
stk_size = stk_size;
pbos = pbos;
opt = opt;
id = id;
#endif

#if OS_TASK_DEL_EN > 0u
ptcb->OSTCBDelReq = OS_ERR_NONE; (5)
#endif

#if OS_LOWEST_PRIO <= 63u
ptcb->OSTCBY = (INT8U)(prio >> 3u); (6)
ptcb->OSTCBX = (INT8U)(prio & 0x07u);
#else
ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0xFFu);
ptcb->OSTCBX = (INT8U) (prio & 0x0Fu);
#endif

ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY);
ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX);


#if OS_EVENT_EN > 0u
ptcb->OSTCBEventPtr = (OS_EVENT *)0; (7)
#if (OS_EVENT_MULTI_EN > 0u)
ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif

#endif

#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) && (OS_TASK_DEL_EN > 0u)
ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; (8)
#endif

#if OS_MBOX_EN || (OS_Q_EN && (OS_MAX_QS >= 2))
ptcb->OSTCBMsg = (void *)0;
#endif

#if OS_TASK_PROFILE_EN > 0u
ptcb->OSTCBCtxSwCtr = 0uL;
ptcb->OSTCBCyclesStart = 0uL;
ptcb->OSTCBCyclesTot = 0uL;
ptcb->OSTCBStkBase = (OS_STK *)0;
ptcb->OSTCBStkUsed = 0uL;
#endif
#if OS_TASK_NAME_EN > 0u
ptcb->OSTCBTaskName = (INT8U *)(void *)"?";
#endif
#if OS_TASK_REG_TBL_SIZE > 0u
for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) {
ptcb->OSTCBRegTbl[i] = 0u;
}

#endif
OSTCBInitHook(ptcb); (9)

OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = ptcb; (10)
OS_EXIT_CRITICAL();

OSTaskCreateHook(ptcb); (11)

#if OS_TASK_CREATE_EXT_EN > 0u
#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)
for (j = 0u; j < OS_TLS_TBL_SIZE; j++) {
ptcb->OSTCBTLSTbl[j] = (OS_TLS)0;
}
OS_TLS_TaskCreate(ptcb);
#endif
#endif

OS_ENTER_CRITICAL(); (12)
ptcb->OSTCBNext = OSTCBList;
ptcb->OSTCBPrev = (OS_TCB *)0;
if (OSTCBList != (OS_TCB *)0) {
OSTCBList->OSTCBPrev = ptcb;
}
OSTCBList = ptcb;
OSRdyGrp |= ptcb->OSTCBBitY; (13)
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
OSTaskCtr++;
OS_EXIT_CRITICAL();
return (OS_ERR_NONE); (14)
}
OS_EXIT_CRITICAL();
return (OS_NO_MORE_TCB);
}

TCB初始化函数主要完成TCB的分配和调度相关的初始化,同时还提供了两个钩子函数OSTCBInitHook和OSTaskCreateHook,这两个函数是可用于用户对任务进行独立配置。

$\mu$C/OS-$\amalg$的调度管理

就绪队列

优先级表


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 yxhlfx@163.com

文章标题:UCOS的任务管理

本文作者:红尘追风

发布时间:2018-01-10, 10:26:46

原始链接:http://www.micernel.com/2018/01/10/%E4%BB%BB%E5%8A%A1%E6%8E%A7%E5%88%B6%E5%9D%97%E5%8F%8A%E5%85%B6%E5%88%9D%E5%A7%8B%E5%8C%96/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录