UCOS+时间片轮转调度算法详解

  • 格式:doc
  • 大小:62.50 KB
  • 文档页数:11

UCOS 时间片轮转调度算法详解2009年8月4日能使信号量代码产生||能使互斥量代码产生 */OS_EVENT *OSTCBEventPtr; /*指向事件控制块的指针*/#endif#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() 指向传递给任务的消息的指针*/#endif#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) #if OS_TASK_DEL_EN > 0 /*OS版本大于等于251&&能使事件标志代码产生&&最大标志数大于零*/OS_FLAG_NODE *OSTCBFlagNode; /*指针指向事件标志节点*/#endifOS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run事件标志使任务准备运行*/#endifINT16U OSTCBDly; /* 任务等待的时限*/INT8U OSTCBStat; /* 任务的当前状态标志 */INT8U OSTCBPrio; /* 任务优先级 (0 == highest, 63 == lowest) */ /*以下四行语句用于快速访问就绪表的数据*/INT8U OSTCBX; /* Bit position in group corresponding to task priority (0..7) */INT8U OSTCBY; /* Index into ready table corresponding to task priority */INT8U OSTCBBitX; /* Bit mask to access bit position in ready table */INT8U OSTCBBitY; /* Bit mask to access bit position in ready group */#if OS_TASK_DEL_EN > 0BOOLEAN OSTCBDelReq; /* Indicates whether a task needs to delete itself */#endif/*********************************************************************** 以下代码是我自己加的:********************************************************************* */#ifdef OS_TIME_SCHEDULEstruct os_tcb *OSTSnext;struct os_tcb *OSTSprev;INT8U OSTSLen; /*记录了该进程占用多少个时间片*/INT8U OSTSCurLen; /*记录的是该进程现在还剩下多少个时间片时间可以用*/#endif/********************************************************************** */} OS_TCB;三.进程创建进程创建的主要目的是跳过原代码中的优先级占用检查,并在这里加入FIFO 进程创建。

文件在OS_TASK.C中:INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos,INT8U prio,INT16U id, INT8U TSlen){#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储空间*/ OS_CPU_SR cpu_sr;//CPU状态字是十六位 cpu_sr为OS_CPU_SR型变量#endifOS_STK *psp; //创建一个指向数据类型为OS_STK的指针和一个8位的整型数INT8U err;#if OS_ARG_CHK_EN > 0if (prio > OS_LOWEST_PRIO) { /*保证优先级在允许范围内 */return (OS_PRIO_INVALID);}#endifOS_ENTER_CRITICAL(); /*OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()为定义的宏,用来关闭、打开CPU 的中断。

*/ if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /*保证优先级没有被其它任务占用 *//********************************************************************** * if you want run the FIFO mask this codeOSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing ... *//* ... the same thing until task is created. *///那就是说有一个任务存在了,不再是 Nul/********************************************************************** */OS_EXIT_CRITICAL();psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); /* 初始化任务堆栈,即建立任务堆栈*/err = OS_TCBInit(prio, psp, (OS_STK *)0, id, 0, (void *)0, 0, TSlen);/*初始化任务控制块,从空闲的OS_TCB缓冲池中获得并初始化一个任务控制块*/if (err == OS_NO_ERR) { //如果初始化没有错OS_ENTER_CRITICAL();//进入临界状态OSTaskCtr++; /*任务数量加一*/OS_EXIT_CRITICAL();if (OSRunning == TRUE) { /* 如果多任务开始,寻找最高优先级任务*/ OS_Sched();}} else { //如果初始化任务控制块有错OS_ENTER_CRITICAL();OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others 把这一优先级给其它任务*/OS_EXIT_CRITICAL();}return (err); //返回错误信息/********************************************************************** */else //这是FIFO的任务创建代码{OS_EXIT_CRITICAL();psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); /* Initialize the task's stack初始化任务堆栈,即建立任务堆栈*/err = OS_TCBInit(prio, psp, (OS_STK *)0, id, 0, (void *)0, 0, TSlen);if (err == OS_NO_ERR) {OS_ENTER_CRITICAL();OSTaskCtr++; /*任务数量加一*/OS_EXIT_CRITICAL();if (OSRunning == TRUE) { /* Find highest priority task if multitasking has started */OS_Sched();}}return(err);}/********************************************************************** */OS_EXIT_CRITICAL();return (OS_PRIO_EXIST);}其中加入的传递参数有两个,一个是 id,一个是 TSLen因为会出现同优先级的任务,那么采用优先级做为任务 ID的方式是不可取的了,我们必须加入任务 id 段TSLen 段,是该进程的时间片为多长。

四.进程初始化进程初始化基本保留以前的东西不动,要的就仅仅是把 TSLen 加入 TCB,把上面说到的那个链表链接起来。

代码在文件OS_CORE.C中初始化任务控制块7opt :传到OSTaskCreateExt()时可以选择,被OSTaskCreate()调用的时候为0。

INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos,INT16U id, INT32U stk_size, void *pext, INT16U opt, INT8U TSlen) {#if OS_CRITICAL_METHOD == 3 /*为CPU状态寄存器分配存储空间 */OS_CPU_SR cpu_sr;#endifOS_TCB *ptcb;OS_ENTER_CRITICAL();ptcb = OSTCBFreeList; /*从空TCB列表中得到一块空TCB */if (ptcb != (OS_TCB *)0) { //分配空TCB成功OSTCBFreeList = ptcb->OSTCBNext; /*更新空闲TCB链表头指针 */ OS_EXIT_CRITICAL();ptcb->OSTCBStkPtr = ptos; /*保存栈顶指针到TCB */ptcb->OSTCBPrio = (INT8U)prio; /*保存任务优先级到TCB */ptcb->OSTCBStat = OS_STAT_RDY; /*任务状态设为就绪*/ptcb->OSTCBDly = 0; /*任务不延时*/#if OS_TASK_CREATE_EXT_EN > 0ptcb->OSTCBExtPtr = pext; /*存储TCB扩展指针*/ptcb->OSTCBStkSize = stk_size; /*存储堆栈大小 */ptcb->OSTCBStkBottom = pbos; /*存储栈底指针*/ptcb->OSTCBOpt = opt; /*存储任务选项 */#else//以下四条语句用于防止编译器警告,不要删除pext = pext; /* Prevent compiler warning if not used */stk_size = stk_size;pbos = pbos;opt = opt;#endifptcb->OSTCBId = id; /* 存储任务ID */#if OS_TASK_DEL_EN > 0 //允许包含任务删除代码ptcb->OSTCBDelReq = OS_NO_ERR; //是否允许自动删除#endifptcb->OSTCBY = prio >> 3; /*提前计算X,Y,位X,位Y*/ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];ptcb->OSTCBX = prio & 0x07;/* 存储就绪优先级组中的 8 个优先级情况*/ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX]; /*为什么要这样算?不知道 */#if OS_EVENT_EN > 0ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* 任务不等待任何事件发生*/ #endif#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0)/*OS版本大于等于251&&能使事件标志代码产生&&最大标志数大于零&& 允许包含任务删除函数*/ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* 任务不等待事件标志*/#endif#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0))//允许邮箱代码产生||允许队列代码产生&&最大队列控制块大于零ptcb->OSTCBMsg = (void *)0; /*没有接收到任务消息*/#endifptcb->OSTSLen=TSlen;ptcb->OSTSCurLen=TSlen;#if OS_VERSION >= 204 //ucos版本大于等于204OSTCBInitHook(ptcb);#endifOSTaskCreateHook(ptcb); /* Call user defined hook */OS_ENTER_CRITICAL();if(OSTCBPrioTbl[prio] == 0){OSTCBPrioTbl[prio] = ptcb; /*任务控制块存入到已创建任务控制块列表当中*/ptcb->OSTSnext = ptcb;ptcb->OSTSprev = ptcb;}else{ptcb->OSTSnext = OSTCBPrioTbl[prio]->OSTSnext;OSTCBPrioTbl[prio]->OSTSnext = ptcb;ptcb->OSTSprev = OSTCBPrioTbl[prio];(ptcb->OSTSnext )->OSTSprev=ptcb;}ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ptcb->OSTCBPrev = (OS_TCB *)0;if (OSTCBList != (OS_TCB *)0) {OSTCBList->OSTCBPrev = ptcb;}OSTCBList = ptcb;OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;OS_EXIT_CRITICAL();return (OS_NO_ERR);}OS_EXIT_CRITICAL();return (OS_NO_MORE_TCB);}---------------------------------------if(OSTCBPrioTbl[prio] == 0){OSTCBPrioTbl[prio] = ptcb;ptcb->OSTSnext = ptcb;ptcb->OSTSprev = ptcb;}else{ptcb->OSTSnext = OSTCBPrioTbl[prio]->OSTSnext;OSTCBPrioTbl[prio]->OSTSnext = ptcb;ptcb->OSTSprev = OSTCBPrioTbl[prio];(ptcb->OSTSnext )->OSTSprev=ptcb;}这一段解释一下链表必须进行链接,在优先级没有被占用的时候,这个链表的前后都链向自己,这样在调度的时候,FIFO 调度就算指向下个任务,也指向的是自己,不影响优先级调度。