热爱开源,喜欢分析操作系统架构
分类: 嵌入式
2013-04-25 20:57:34
多任务系统自然以任务为核心,在启动任务机制之后,MQX要么在任务中运行,要么就在中断服务程序里。相比linux还多了一个内核态,MQX则将内核操作也任务化了(权限比较高),如ipc任务。
MQX的任务可以在初始化的时候创建,也可以在任务运行时动态创建,还是比较灵活的,这都是建立在于动态内存分配的基础之上的。关于任务,有两个非常重要的结构体task_template_struct和td_struct,前者是任务的模板,后者是任务的实体。
MQX根据task_template_struct里的一系列参数来创建td_struct,每一个td_struct都要对应一个task_template_struct。而一个task_template_struct可以对应多个td_struct,几个共用同一个task_template_struct有种线程组的味道,因为它们的执行的函数都是完全相同的,不过由于它们参数和堆栈不一定相同。
MQX 的任务是以链表形式组织的,
这是一个非常典型的双向链表TD_LIST是链表头,INSERT_TD_PTR是链表尾, 新加的任务一个个按顺序加到这个链表尾部的INSERT_TD_PTR上。这个简单的链表是用来记录全局任务增减的,而为了任务调度更加快速,MQX还有一个复杂一点的链表结构。
从图中我们可以看出优先级队列READY_Q_STRUCT按照优先级构成了一个单向的链表,其中READY_Q_LIST指向最高的优先级队列,一般都是0号优先级,而CURRENT_READY_Q指向当前任务的优先级n,最低优先级是初始最低优先级加2(由于优先级队列是初始化时创建的,MQX不会动态的更新链表,因此动态创建的任务优先级最低为初始最低优先级加2)。每个优先级队列都有一个td_struct的双向链表,管理着处于运行态的该优先级的所有任务。通过这个链表结构,我们可以很容易的找到当前优先级最高的任务.(只需要顺着READY_Q_LIST往下,找到第一个不为空的READY_Q_STRUCT里面的HEAD_READY_Q指向的任务就可以了。)
再来说一下任务的堆栈和td_struct的内存分配,这里有两种情况:如果给定了相应的内存空间,td_struct和任务堆栈是连续分配在这块空间上的;如果没有指定相应的内存空间,MQX会分别给td_struct和任务堆栈动态分配内存空间,这个很简单。我下面给出后一种情况的分布图。
如果任务的模拟是动态生产的话会划出堆栈的底部做为存放空间。这里要特别注意STACK_PTR也就是堆栈的指针,在任务刚刚初始化之后,其指向PSP_STACK_START_STRUCT这么一个结构体,具体内容如图所示。如果大家没有记错的话这个堆栈顺序是不是和arm中断的堆栈顺序很像(无FPU),这个就是为任务第一次运行准备一个人工的堆栈环境(如果说arm中断时自动堆栈的话,这个就是我们手工堆出来的一个栈)。请大家牢记这个图,因为它会起到关键的作用。