UCOSII操作系统 第4课—任务管理

UCOSII操作系统 第4课—任务管理1 重讲任务 1 任务可以是一个无限的循环 也可以在一次执行完毕后被删除 这里需要注意的是 任务的代码并不是真正的删除了 而是 UCOSII 不再理会该任务代码 所以该任务代码不会再执行 2 建立任务 OSTaskCreate 如果想让 UCOSII 管理用户的任务 必须先建立任务 可以通过将任务的地址 函数名 和其他参数传递到这 2 个函数中来建立任务 3 任务可以在多任务调度之前开始建立 也可以在其他的任务中创建需要的任务 但是有一点需要注意的是 在启动 UCOS 之前必须至少得建立一个任务 2 分析

1、重讲任务

(3)任务可以在多任务调度之前开始建立,也可以在其他的任务中创建需要的任务。但是有一点需要注意的是,在启动UCOS之前必须至少得建立一个任务。

2、分析创建任务函数

如果创建的时候检测到任务的优先级比最大的优先级(数值上,实际上是最小)还大的话,那么就直接退出,输出一个错误码。

我们不允许创建任务是在中断中进行的,所以我们也会在中断时创建任务返回一个错误码。

最后就是把刚刚的四个参数赋值到任务当中去,实现任务的创建。

#if OS_TASK_CREATE_EN > 0u INT8U OSTaskCreate (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT8U prio) { 
    OS_STK *psp; INT8U err; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif #ifdef OS_SAFETY_CRITICAL_IEC61508 if (OSSafetyCriticalStartFlag == OS_TRUE) { 
    OS_SAFETY_CRITICAL_EXCEPTION(); } #endif #if OS_ARG_CHK_EN > 0u if (prio > OS_LOWEST_PRIO) { 
    /* 确认优先级在一个合法的范围内 */ return (OS_ERR_PRIO_INVALID); } #endif OS_ENTER_CRITICAL(); if (OSIntNesting > 0u) { 
    /* 确保我们不在中断中创建任务 */ OS_EXIT_CRITICAL(); return (OS_ERR_TASK_CREATE_ISR); } if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { 
    /* 初始化任务的优先级 */ OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ /* ... the same thing until task is created. */ OS_EXIT_CRITICAL(); psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* 初始化任务堆栈 */ err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u); if (err == OS_ERR_NONE) { 
    if (OSRunning == OS_TRUE) { 
    /* Find highest priority task if multitasking has started */ OS_Sched(); } } else { 
    OS_ENTER_CRITICAL(); OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */ OS_EXIT_CRITICAL(); } return (err); } OS_EXIT_CRITICAL(); return (OS_ERR_PRIO_EXIST); } #endif 

3、再谈任务堆栈

任务的堆栈可以使用静态的堆栈生成,也可以使用动态的堆栈生成。

(1)静态堆栈:

static OS_STK MyTaskStack[stack_size]; 

(2)动态堆栈:

OS_STK *pstk; pstk = (OS_STK *)malloc(stack_size); if(pstk != (OS_STK *)0) { 
    //确保malloc能够得到足够的内存空间 } 
OS_STK TaskStack[TASK_STACK_SIZE]; OSTaskCreate(task, pdata, &TaskStack[0], prio); 

这个是堆栈从上往下增长的:

OS_STK TaskStack[TASK_STACK_SIZE]; OSTaskCreate(task, pdata, &TaskStack[TASK_STACK_SIZE-1], prio); 
#if OS_TASK_DEL_EN > 0u INT8U OSTaskDel (INT8U prio) { 
    #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) OS_FLAG_NODE *pnode; #endif OS_TCB *ptcb; #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0u; #endif if (OSIntNesting > 0u) { 
    /* See if trying to delete from ISR */ return (OS_ERR_TASK_DEL_ISR); } if (prio == OS_TASK_IDLE_PRIO) { 
    /* Not allowed to delete idle task */ return (OS_ERR_TASK_DEL_IDLE); } #if OS_ARG_CHK_EN > 0u if (prio >= OS_LOWEST_PRIO) { 
    /* Task priority valid ? */ if (prio != OS_PRIO_SELF) { 
    return (OS_ERR_PRIO_INVALID); } } #endif /*$PAGE*/ OS_ENTER_CRITICAL(); if (prio == OS_PRIO_SELF) { 
    /* See if requesting to delete self */ prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */ } ptcb = OSTCBPrioTbl[prio]; if (ptcb == (OS_TCB *)0) { 
    /* Task to delete must exist */ OS_EXIT_CRITICAL(); return (OS_ERR_TASK_NOT_EXIST); } if (ptcb == OS_TCB_RESERVED) { 
    /* Must not be assigned to Mutex */ OS_EXIT_CRITICAL(); return (OS_ERR_TASK_DEL); } OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX; if (OSRdyTbl[ptcb->OSTCBY] == 0u) { 
    /* 把该任务从就绪表中删除,也就是置0处理 */ OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; } #if (OS_EVENT_EN) if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) { 
    OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr); /* 把该任务从事件控制块的列表中移除 */ } #if (OS_EVENT_MULTI_EN > 0u) if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { 
    /* Remove this task from any events' wait lists*/ OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr); } #endif #endif #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) pnode = ptcb->OSTCBFlagNode; if (pnode != (OS_FLAG_NODE *)0) { 
    /* If task is waiting on event flag */ OS_FlagUnlink(pnode); /* 从事件标志组中移除 */ } #endif ptcb->OSTCBDly = 0u; /* 禁止时间等待 */ ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */ ptcb->OSTCBStatPend = OS_STAT_PEND_OK; if (OSLockNesting < 255u) { 
    /* Make sure we don't context switch */ OSLockNesting++; } OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */ OS_Dummy(); /* ... Dummy ensures that INTs will be */ OS_ENTER_CRITICAL(); /* ... disabled HERE! */ if (OSLockNesting > 0u) { 
    /* Remove context switch lock */ OSLockNesting--; } OSTaskDelHook(ptcb); /* Call user defined hook */ OSTaskCtr--; /* One less task being managed */ OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */ if (ptcb->OSTCBPrev == (OS_TCB *)0) { 
    /* Remove from TCB chain */ ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0; OSTCBList = ptcb->OSTCBNext; } else { 
    ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext; ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev; } ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */ OSTCBFreeList = ptcb; #if OS_TASK_NAME_EN > 0u ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; #endif OS_EXIT_CRITICAL(); if (OSRunning == OS_TRUE) { 
    OS_Sched(); /* Find new highest priority task */ } return (OS_ERR_NONE); } #endif 5、挂起任务,OS_TaskSuspend()和恢复挂起任务OSTaskResume() (1)这个函数是必须进行说明的一个函数,因为他涉及到任务的状态机。 (2)这个实现挂起的函数主要是删除就绪表中的位图的相应优先级的那个位进行置0的操作。 (3)然后将任务的相应的状态进行赋值为挂起的状态。 (4)最后在最后要进行任务的调度的操作,如果当前是这个任务在进行的话,要切换到别的任务中继续去运行。 INT8U OSTaskSuspend (INT8U prio) { 
    BOOLEAN self; OS_TCB *ptcb; if (prio == OS_IDLE_PRIO) { 
    (1) return (OS_TASK_SUSPEND_IDLE); } if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { 
    (2) return (OS_PRIO_INVALID); } OS_ENTER_CRITICAL(); if (prio == OS_PRIO_SELF) { 
    (3) prio = OSTCBCur->OSTCBPrio; self = TRUE; } else if (prio == OSTCBCur->OSTCBPrio) { 
    (4) self = TRUE; } else { 
    self = FALSE; } if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) { 
    (5) OS_EXIT_CRITICAL(); return (OS_TASK_SUSPEND_PRIO); } else { 
    if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) { 
    (6)//就绪表中的相应的位置0操作 OSRdyGrp &= ~ptcb->OSTCBBitY; } ptcb->OSTCBStat |= OS_STAT_SUSPEND; (7) 把TCB的状态也设置为挂起的状态标志位 OS_EXIT_CRITICAL(); if (self == TRUE) { 
    (8) OSSched(); } return (OS_NO_ERR); } } 

OSTaskResume()恢复任务的源码也是差不多的,就是一个是对就绪表上面的内容进行置0的操作,一个是对就绪表的内容进行置1的操作。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227024.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午10:07
下一篇 2026年3月16日 下午10:07


相关推荐

  • 沧州文化_沧州古代雅称

    沧州文化_沧州古代雅称沧洲东临渤海,北靠京津,有利的地形形成了四通八达的交通。沧州文化历史悠久,从战国时期沧州就因渤海而得名。沧州人民民风淳朴、勇敢、刚强加上历史的条件关系被人民称为“武建泱泱乎有表海熊风” 沧州的“武术之乡”已被四方的人知晓,那么沧州本土文化你又了解多少?本专题带您了解更多关于沧州文化的内容。农业特产沧州金丝小枣金丝小枣沧州红枣又称金丝小枣,沧县、献县、泊头交界处及其周围是金丝小枣生产地。其中…

    2022年8月18日
    16
  • java四舍五入取整算法(小数四舍五入取整公式)

    简介Math类中提供了5个与取整相关的函数,如下所示:staticdoubleceil(doublea):天花板函数,返回大于等于a的最小整数(但是以浮点数形式存储)。staticdoublefloor(doublea):地板函数,返回小于等于a的最大整数(但是以浮点数形式存储)。staticdoublerint(doublea):四舍五入函数,返

    2022年4月16日
    382
  • 智谱GLM-5“身份”揭晓:复用DeepSeek架构参数翻倍,市值飙升坐实国产AI领跑者

    智谱GLM-5“身份”揭晓:复用DeepSeek架构参数翻倍,市值飙升坐实国产AI领跑者

    2026年3月12日
    2
  • BD和DVD区域划分

    BD和DVD区域划分BD和DVD区域划分BD:A区:只能是在美国、日本以及香港、台湾等东南亚地区正常播放;B区:只能在欧洲和澳洲等国家正常播放;C区:是在中国大陆、俄罗斯和印度三国才能正常播放。DVD:第一区为:美国、加拿大;第二区为:日本、欧洲、埃及、南非、中东;第三区为:中国台湾、中国香港特别行政区、南韩、东南亚;第四区为:澳洲、新西兰、中南美洲、南太平洋岛屿;第五区为:俄罗斯、蒙古、印度

    2022年7月11日
    36
  • nginx与uWSGI[通俗易懂]

    nginx与uWSGI[通俗易懂]今天同事问了我一个问题,nginx和uWSGI的区别是啥?我当时答出了反向代理和静态文件,后来聊到了负载均衡,所以好好查了下两者的区别。首先来了解几个概念:WSGIWSGI的全称是WebServerGatewayInterface(Web服务器网关接口),它不是服务器、python模块、框架、API或者任何软件,只是一种描述web服务器(如nginx,uWSGI等服务器)如何与…

    2025年10月28日
    6
  • python小项目:1、人机剪刀石头布

    python小项目:1、人机剪刀石头布

    2021年10月5日
    41

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号