LiteOS中任务管理功能的的认识和理解(LOS_TASK_CB结构体)-0x01
在嵌入式系统开发中,在没有操作系统的裸机程序一般只有一个任务,即从main开始的无限循环的程序。而有了操作系统之后,嵌入式系统就可以实现多个任务的运行,这可以极大的提高嵌入式系统的软件功能。通常,实现多任务的运行管理功能是一个操作系统的核心功能。Lite OS也一样。在Lite OS 的任务运行和管理功能中,有个非常重要的结构体LOS_TASK_CB,称为任务控制块。每个任务都有一个属于自己的任务块实例。这个任务控制块中包含了该任务的很多信息。正确的理解和分析这个结构体成员变量的含义,有助于理解Lite OS中的任务相关的概念,有助于用好Lite OS系统。
如下图是LOS_TASK_CB的定义,它总共有19个成员变量。
1. void *pStackPointer: 栈指针,指向任务栈空间的指针。
每一个任务都拥有一个独立的栈空间。任务栈空间,就是系统为这个任务在内存里面分配的一块存储区域,在这个存储区域里面存放的这个任务相关的局部变量、寄存器、函数参数、函数返回地址等。
当系统中有多个任务运行时,可能发生任务的切换。即暂停某个任务的运行(即某一个任务被阻塞了),而让另外一个任务运行(即另外一个任务进入运行状态)。当发生任务切换时,会将暂停运行的任务的上下文信息保存在自身的任务栈空间里面,以便任务恢复时还原现场,从而在任务恢复后在切出点继续开始执行。
在用户创建自己的任务的时候,需要设定好任务栈空间的大小。任务栈空间的大小设置多少比较合适,即不浪费内存够,也不至于发生栈溢出的问题?这个暂时没看到更具体的说明,或者计算方法。
2.UINT16 usTaskStatus:表示任务的状态。
通常在理论分析或者设计的时候,会说Lite OS 中的任务通常有四种状态,即就绪(Ready),运行(Running),阻塞(Blocked),退出态(Dead)。在程序中有如下宏定义来表示一个任务或者任务块的更加具体的状态。
#define OS_TASK_STATUS_UNUSED 0x0001
#define OS_TASK_STATUS_SUSPEND 0x0002
#define OS_TASK_STATUS_READY 0x0004
#define OS_TASK_STATUS_PEND 0x0008
#define OS_TASK_STATUS_RUNNING 0x0010
#define OS_TASK_STATUS_DELAY 0x0020
#define OS_TASK_STATUS_TIMEOUT 0x0040
#define OS_TASK_STATUS_EVENT 0x0400
#define OS_TASK_STATUS_EVENT_READ 0x0800
#define OS_TASK_STATUS_SWTMR_WAIT 0x1000
#define OS_TASK_STATUS_PEND_QUEUE 0x2000
#define OS_TASK_STATUS_PEND_MUT 0x4000
#define OS_TASK_STATUS_PEND_SEM 0x8000
这些状态的意义可以根据宏定义的名称略知一二,在程序源码中也有更详细的说明,在这里就不在赘述了。
3. UINT32 usPriority: 任务的优先级。数值越大,代表优先级越低。多个处在就绪状态的任务,要执行的时候,优先级高的任务将被优先执行。
4. UINT32 uwStackSize: 任务栈空间的大小。在创建任务的时候,可以通过设置这个成员变量,来指定任务栈空间的大小。在程序中,有两个相关宏定义,如下。
#define OS_TASK_PRIORITY_HIGHEST 0
#define OS_TASK_PRIORITY_LOWEST 31
从这两个宏定义可以看出,Lite OS 中任务的最高优先级是0,最低优先级是31,总共有32个优先级。
5. UINT32 uwTopOfStack: 任务栈的栈顶。如下简单示意了,在任务栈空间中栈顶,栈底,栈指针的相对位置关系。通常栈顶所指向的是栈空间中内存地址最小的单元。uwTopOfStack + uwStackSize = uwBottomOfStack。这里的uwBottomOfStack指向的是栈底,在TSK_INFO_S结构体中有使用它。
6. UINT32 uwTaskID: 任务的编号。系统中可以运行多个任务,给每个任务一个编号,便于任务管理。任务的编号,Lite OS 系统内核初始化的时候,已经根据配置的最大任务数量,为每个任务配置了任务编号。见如下程序段中的513行。
7. TSK_ENTRY_FUNC pfnTaskEntry: 任务的入口函数。每个新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体指定。
这个入口函数跟没有操作系统的嵌入式C程序中的main函数有点相似。如果将main函数看成一个任务,那么在具有多个任务的操作系统中,需要给每个任务指定它的入口函数,就像是指定了多个main函数一样。
8. void *pTaskSem: 与任务相关的信号量。
9. void *pTaskMux: 与任务相关的互斥量
10. UINT32 uwArg: 任务相关的参数。通常用来当做入口函数的参数。类似一些C/C++程序中带参数的main函数的参数,例如void main(int argc,char *argv[])中的argc,argv[ ]参数。
11. char *pcTaskName: 任务的名字。用户自己定义,名字的含义有助于理解这个任务的功能。
12. LOS_DL_LIST stPendList: 引起这个任务挂起的对象列表。引起该任务挂起的对象,会由系统统一调度和管理。
13. LOS_DL_LIST stTimerList: 与这个任务相关的定时器列表。由用户
14. UINT32 uwIdxRollNum: 与任务调度运行相关的变量。
15. EVENT_CB_S uwEvent: 与任务相关的事件控制块变量。
16. UINT32 uwEventMask: 事件的掩码
17. UINT32 uwEventMode: 事件的模式
18. void *puwMsg: 指向队列存储区域的指针
19. struct _reent stNewLibReent: 新库的_reent结构体变量。
从第8-第19个成员变量,用户在使用过程中用的比较少,更多用于系统内部功能实现。与之相关的信号量、互斥量、事件、队列等在LiteOS的开发说明中有相关的更详细的内容。
以上仅仅是个人的一些理解和认识,有不正确或者不全的欢迎大家指出和补充,分享学习,共同进步。
- 点赞
- 收藏
- 关注作者
评论(0)