zoukankan      html  css  js  c++  java
  • UCOS 请求任务删除函数 及其应用

    有时候,如果任务A拥有内存缓冲区或信号量之类的资源,而任务B想删除该任务,这些资源就可能由于没被释放而丢失。在这种情况下,用户可以想法子让拥有这些资源的任务在使用完资源后,先释放资源,再删除自己。用户可以通过OSTaskDelReq()函数来完成该功能。

    函数名

    OSTaskDelReq

    参数

    Prio要删除任务的优先级(0xFF表示当前任务)

    功能描述

    请求删除任务

    函数原型

    INT8U OSTaskDelReq(INT8U prio)

     

     

     

    {

        if (prio == OS_PRIO_SELF) //判断调用此函数时,是否使用0xFF表示当前函数的优先级

        {              //调用该函数时,如果要删除当前任务,不知道优先级,可以使用0xFF代替

        

            OS_ENTER_CRITICAL();          //进入临界区0       

             stat = OSTCBCur->OSTCBDelReq; //当前任务收到删除请求

                                          //当被删除任务被调度时,会检查OSTCBDelReq的值

                                          //为OS_TASK_DEL_REQ时,调用OSTaskDel()

       

            OS_EXIT_CRITICAL();           //退出临界区0

            

            return (stat);

        }

        

        OS_ENTER_CRITICAL(); //进入临界区0

        ptcb = OSTCBPrioTbl[prio];

        if (ptcb != (OS_TCB *) 0) //判断要删除的任务是否存在

        {

            ptcb->OSTCBDelReq = OS_TASK_DEL_REQ; //要删除的任务收到删除请求(记录在TCB中)

            err = OS_NO_ERR;

        }

        else //删除的任务不存在

        {

            err = OS_TASK_NOT_EXIST; //

        }

        OS_EXIT_CRITICAL(); //退出临界区0

        

        return (err); //返回删除的信息

    }

    本文就该函数做了细致,深入的解答。并借用网友的例子和邵贝贝书上的例子,讲解了一般的问题和常用的用法。带了自己的感想和思考。希望对自己有帮助。做此记录。

    在ucos中这个函数很常用,个人觉着,使用OSTaskDel,是有风险的,因为他会删除那些变量。比如下面的一篇文章的部分内容。

    慎用OSTaskDel(OS_PRIO_SELF);OSTaskSuspend(OS_PRIO_SELF);   

    OSTaskDel(OS_PRIO_SELF);这个函数,把该任务使用到的变量都给删除了!

    比如,在Wake_Modem();中使用到了

    char txmsg;

    .................

    txmsg ='7';
     OSQPost(QSem, (void *)&txmsg);

    而在另一个任务中等待该消息,

    char *rxmsg = 0;

    ....................

    rxmsg=(char *)OSQPend(QSem, 0, &err); 
      switch(*rxmsg)
      {                  case '7':
                       OS_ENTER_CRITICAL();
                       Uart_Select(0);
                      Uart_Init(0,115200);
                       Uart_Printf("OK! ");
                    OS_EXIT_CRITICAL();
                    break;

    }

    程序则无法输出OK,因为OSTaskDel(OS_PRIO_SELF);这个函数的存在,导致txmsg也被删除了!

    OSTaskSuspend(OS_PRIO_SELF); 与之同效!

    解决办法:static char txmsg;

    下面是OSTaskDelReq的用法。

    一、发出删除任务请求的任务和打算被时删除的任务都必须调用 OSTaskDelReq() 函数

    举个例子:请求删除其他任务的任务,设为 Task-1。

    要被删除的任务,设为 Task-2。其实就是 Task-1删除Task-2.

    Task-1 确定要删除 Task-2,那么Tak-1 发出删除请求:OSTaskDelReq( TASK_TO_DEL_PRIO),其中TASK_TO_DEL_PRIO  是 Task-2 的优先级号,假设优先级号在正常范围内,Task-2 确实已经建立。

    那么,这样一来,OS_TASK_DEL_REQ 标志就会被存往 Task-2 的 TCB 中,代码见 OSTaskDelReq() 中的:

    if (ptcb != (OS_TCB *)0)
     {                                 
            ptcb->OSTCBDelReq = OS_TASK_DEL_REQ;             /* 存删除请求标志*/ 
            err = OS_NO_ERR;
    }

    当 OSTaskDelReq() 返回时,带回的返回值是 OS_NO_ERR。(这与上面的假设成为因果)

    表明请求已经被接受,但 TASK-2 还没被删除,所以 TASK-1 选择等待。在我的试验里,Task1是个具体的任务,他的优先级高,而task2的优先级低,于是优先级高的任务运行时,可以删除task2.
    --------------------------
    当轮到 TASK-2 开始执行时,它也会调用 OSTaskDelReq( OS_PRIO_SELF ) 检查自身。                 这时,在OSTaskDelReq() 的 if( prio == OS_PRIO_SELF ) 程序块中,从自己的 TCB中得到了之前所存的标志:OS_TASK_DEL_REQ。这样,TASK-2 已经确认了自己要被别的任务删除了,所以接下来它就释放所占用的资源还有释放所有的动态内存。完后,调用 OSTaskDel( OS_PRIO_SELF )删除自身。

    至此,假设 TASK-2 在删除自身后,并没有更高的优先级任务出现,依然是 TASK-1 在执行。记得 TASK-1在发送删除请求时,是在一直循环等待着的,它等待的是一个叫做 OS_TASK_NOT_EXIT的标志。所以,当再一次调用OSTaskDelReq() 时,由于OSTaskDelReq() 中的 if( ptcb != (OS_TCB*)0) 不成立( ptcb == (OS_TCB *)0 ),则理所当然的得到 OS_TASK_NOT_EXIT这个标志。至此,TASK-1 成功完成了删除 TASK-2 的任务。

    上面的内容在邵贝贝的书:133页,有例子:

    要删除别人的是这么写的:

    If()

    {

    While(OSTaskDelReq(被删的优先级号)!=OS_TASK_NOT_Exist)

    {

      OSTimeDly(1);//这个有点就行

    }

    }

    被删的任务是这样写的

    If(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ)

    {

    释放所占用的资源;//这里才是重点

    释放动态内存;

    OSTaskDel(OS_PRO_SELF);

    }

    Else

    {

    其他代码!

    }
    //明白了吧,原来,这个函数是要用它的参数的,其实他并不去主动的释放那些东西的。

    他只是去做那些过程中事情。说白了,他就是i一个电话。
    另外,如果没有任何任务发出请求要删除 TASK-2,而 TASK-2 只是在检查自身是否要被删除时,它得不到OS_TASK_DEL_REQ 这个标志,那么就只能继续执行自己的代码。 
    -----------------------------------------------
    OSTASKDelReq() 的代码见下:

    #if OS_TASK_DEL_EN > 0
    INT8U  OSTaskDelReq (INT8U prio)
    {
    #if OS_CRITICAL_METHOD == 3                     
        OS_CPU_SR  cpu_sr;
    #endif
        BOOLEAN    stat;
        INT8U      err;
        OS_TCB    *ptcb;

    #if OS_ARG_CHK_EN > 0
        if (prio == OS_IDLE_PRIO) {                                 /*不允许删除空闲任务*/
            return (OS_TASK_DEL_IDLE);
        }
        if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {       /* 任务优先级合法?*/
            return (OS_PRIO_INVALID);
        }
    #endif
        if (prio == OS_PRIO_SELF) {                                 /* See if a task is requesting to ...  */
            OS_ENTER_CRITICAL();                                    /* ... this task to delete itself      */
            stat = OSTCBCur->OSTCBDelReq;                           /* Return request status to caller     */
            OS_EXIT_CRITICAL();
            return (stat);
        }
        OS_ENTER_CRITICAL();
        ptcb = OSTCBPrioTbl[prio];
        if (ptcb != (OS_TCB *)0) {                                  /* Task to delete must exist           */
            ptcb->OSTCBDelReq = OS_TASK_DEL_REQ;                    /* Set flag indicating task to be DEL. */
            err               = OS_NO_ERR;
        } else {
            err               = OS_TASK_NOT_EXIST;                  /* Task must be deleted                */
        }
        OS_EXIT_CRITICAL();
        return (err);
    }
    #endif

     

  • 相关阅读:
    openwrt 更改 debug 等级(hostapd)
    openwrt 中procd
    openwrt增加串口登录需要密码
    openwrt设置语言的过程
    小程序感悟123
    如何用php实现分页效果
    如何利用h5将视频设置为背景
    关于js中定时器的返回值问题
    canvas二:绘制圆和其他曲线
    canvas一:基本认识
  • 原文地址:https://www.cnblogs.com/locean/p/5511078.html
Copyright © 2011-2022 走看看