有时候,如果任务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!\n");
                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

 

UCOS 请求任务删除函数 及其应用的更多相关文章

  1. Shell函数:Shell函数返回值、删除函数、在终端调用函数

    函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高.像其他编程语言一样,Shell 也支持函数.Shell 函数必须先定义后使用. Shell 函数的定义格式如下: f ...

  2. Shell函数返回值、删除函数、在终端调用函数

    Shell 也支持函数.Shell 函数必须先定义后使用. Shell 函数的定义格式如下: function_name () { list of commands [ return value ] ...

  3. SQLServer之删除函数

    删除函数注意事项 从当前数据库中删除一个或多个用户定义函数.DROP 函数支持本机编译的标量用户定义函数. 如果数据库中存在引用 DROP FUNCTION 的 Transact-SQL 函数或视图并 ...

  4. 【Shell脚本学习22】Shell 函数:Shell函数返回值、删除函数、在终端调用函数

    函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高.像其他编程语言一样,Shell 也支持函数.Shell 函数必须先定义后使用. Shell 函数的定义格式如下: f ...

  5. 笔试算法题(19):判断两条单向链表的公共节点 & 字符集删除函数

    出题:给定两个单向链表的头结点,判断其是否有公共节点并确定第一个公共节点的索引: 分析: 由于是单向链表,所以每个节点有且仅有一个后续节点,所以只可能是Y型交叉(每条链表中的某个节点同时指向一个公共节 ...

  6. js cookie创建读取删除函数封装

    js cookie创建读取删除函数封装 一.总结 都是为了方便操作,这样弄了很方便 1.创建cookie的函数封装的作用:方便设置过期时间expire,方便设置键和值 2.查询cookie的数据封装的 ...

  7. 为什么不能用drop function add 去删除函数? 因为不能使用 mysql中的保留字!

    mysql中有很多的 保留字, 也叫关键字, 你在使用 数据库中的任何东西, 都最好是 避开这些关键字/保留字, 包括 数据库名, 表名, 字段名, 函数名, 存储过程名. 这些关键字包括: mysq ...

  8. ajax请求成功回调函数没有执行问题

    如下常见的ajax前端请求,请求成功后success:function(result){ 这里的数据没有执行 }: $.ajax({ type:"post", url:" ...

  9. 为非ajax请求绑定回调函数的方法

    我们都知道jQuery为ajax请求封装了success和error两个回调方法,其实jQuery也实现了为非ajax请求的普通方法也设计了绑定回调函数的方法. 当一个方法需要等待另一个耗时很长的方法 ...

随机推荐

  1. Bellman_ford最短路

    #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> ...

  2. SqlServer新建视图

    一.使用SQL Server 2005数据库管理系统创建视图 1. 启动SQL Server 2005. 2. 在“对象资源管理器”窗口中找到Student数据库,打开Student文件夹,在“视图” ...

  3. R语言笔记

    R语言笔记 学习R语言对我来说有好几个地方需要注意的,我觉得这样的经验也适用于学习其他的新的语言. 语言的目标 我理解语言的目标就是这个语言是用来做什么的,为什么样的任务服务的,也就是设计这个语言的动 ...

  4. 【1】JAVA---地址App小软件(AddressApp.class)(初步接触项目开发的分层思想)(表现层)

    这个是表现层的main方法. 实现的地址信息有: 姓名,性别,年龄,电话,地址. 实现的功能有: 增加地址: 删除地址: 修改地址: 查找地址:其中年龄的查找为年龄段的查找. 数据存储的方式为文件存储 ...

  5. 进程间通讯aidl

    进程间通讯(aidl) 1.首先定义一个接口 2.把这个接口的文件扩展名改为xxx.aidl 3.写一个MyService类继承自Service类重新里面的方法, 4.在MyService类定义一个内 ...

  6. Intel 英特尔

    英特尔 英特尔 基本资料   公司名称:英特尔(集成电路公司)    外文名称:Intel Corporation(Integrated Electronics Corporation)    总部地 ...

  7. CPU使用率计算

    昨天接到临时任务,需要将一个工作线程执行真正工作的时机推迟到CPU空闲时执行.当时第一感觉认为是将线程优先级设置为空闲级别就行了,以为只有CPU空闲下来才会去跑这个线程,实际上应该不是,毕竟即时是空闲 ...

  8. linux系统目录介绍

    目录/文件 用途 来源 / /处于Linux文件系统树形结构的最顶端,它是Linux文件系统的入口,所有的目录.文件.设备都在/之下. - /bin 该目录存放着系统最常用的最重要的命令,相当于DOS ...

  9. SKCropNode类

    继承自 SKNode:UIResponder:NSObject 符合 NSCoding(SKNode) NSCopying(SKNode) NSObject(NSObject) 框架 /System/ ...

  10. vs2008打包公布程序

    vs2008打包公布程序 一vs2008中新建 安装项目,确定(新建 安装向导 也能够) 二.加入内容 1.加入主要内容: 应用程序目录=>右键=>加入=>文件,找到须要的文件,包含 ...