task 的目的

做过界面的编程的同学可能会有这种经历,界面不响应,那,其实程序总是在后台运行,但是后台可能是个for循环,那么界面的点击等事件都不能执行。

在windows界面编程中利用了事件机制来做,维护了事件的队列,然后有一个线程不停的取出事件然后回调注册的事件处理函数,每个事件处理函数必然是短小的,否则会独占处理器太久,其他操作得不到响应。

在Qt中,为了维持对用户的响应,使用的是signal函数,signal函数触发slot的操作,理论上也应该是短小的操作。

在两种机制中,主线程负责ui方面的响应,要不就是把发生的时间记录下来,要不就是直接signal信号出去,然后立即返回。总体的规则是负责ui的线程中不能出现长时间占用cpu的操作。

task的出现和以上情况是一致的,在使用post task后,函数立即返回,可以执行其他操作,其他组件也可以继续相应用户,所有的task应该是短小的操作,以保证其他的task不会产生太大的延迟。

TinyOS中采用了队列的机制来循环处理task,用线程来讲就好像,由boot触发的main函数像一个主线程,用来记录用户的操作以及各种task,而schedule组件就像是一个负责处理的线程,循环的处理用户已经post的线程,这样,用户的操作,如亮灯、终端等,可以得到及时的响应,外界的信息也不会那么容易的丢失。

task 的机制

在tinyos 1.x中task采用的方式是post task,在2.x中使用BasicTasic接口来进行task的注册,但完全可以用1.x中的方法。

前面提到过post task只是往task队列中添加一条task调用记录,然后由scheduler循环处理,在post task和scheduler真正调用task时,一定会产生延迟,也就是说task的调用是推后的函数调用。

因为在1.x中schedular貌似没有设置task队列的长度,那么意味着一个组件可以无限post task,但实际上这种情况会使得一个组件独占cpu资源。

为了避免这种情况,在2.x中schedular设置了的task的调用数组,数组中的每一项是注册过的task,当task被调用了,就相应的置位,关于顺序问题应该是有做记录(我不知道,求告诉QAQ),这样可以防止一个组件post过多相同的task独占资源。

task 和函数的不同

执行操作不同

最主要的不同在于调用,这也是task存在的意义,就像前面说的,task是为了相应用户而生,调用 task 时在 post 后立即返回,而函数要执行完后返回。

长相也不同

task的标准形式如下

task void 函数名()
{
// do task
}

这意味着task没有返回值,也没有参数。task的思想是为了执行一段操作,调用task时立即返回,所以没有返回值是情理之中,但post task却有返回值,我们等会说。

task 的参数我的想法是,TinyOS 的思想是节点的内存有限,所以尽可能减少临时变量和动态变量这一类变量,所以可以看到文档建议一些变量最好直接在组件中进行定义,没有那么多的内存空间来做函数的栈存储临时变量。

基于以上分析,task不带参数,也不帮你存储参数,但由于这个性质,task运行时可能会产生问题,我们在后面会说到。

是否允许中断,应该说是抢占?

可以明确的是,task是允许中断(我觉的更确切应该说是抢占)的,我想这也是保持用户响应的一部分。同时,我的想法是普通函数是不允许中断的,因为task是允许中断的。。。

async 函数意味着可以异步执行,TinyOS规定 async 函数中不能调用普通函数,也就是同步函数,异步的意思貌似是可以抢占其他函数的执行,或者说是打断,同时自己也可以被抢占。那么如果想要在 async 函数中执行同步代码,就要用到task,也是唯一方式。

task 返回失败的情况

首先post task是有返回值的。

为了防止同一组件不停的post task,Tinyos 2.x中post在有同名task正在队列并且没有执行时返回Fail,应该就是检查task调用数组了,这以为着你开启一个for循环来post数组是不允许的,如下

for (int i = 0; i < 10; i++)
{
post process_message();
}

上面这代码,如果第一个post成功,并且process_message函数执行有一定时间,那么根据TinyOS规定,一个process_message在执行,一个process_message函数在队列,其他的处理函数就都没有得到执行,返回的是Fail。在这种情况下,你的想法是处理10条消息,但实际上只处理了2条。

这样看来,这种情况下你所post task的数目与实际执行的task的数目并不一定相同。

但TinyOS允许task自身调用,如下

task void process_message()
{
// start processing message
...
// finish processing message
process_message()
}

通过这种方式,task应该是不会返回Fail的,因为task实在结尾处调用自身,如果设置一个counter的话,应该可以实现上面的for循环调用。

In TinyOS 2.x, a basic post will only fail if and only if the task has already been posted and has not started execution.

task 只关注当前

按照线程的思维方式,线程所使用的变量都是进程的,这意味着如果其他线程修改了进行的变量,当前线程可能并不知情。

task执行任务是推迟的,并且task是允许中断的,这意味这在使用post task后,组件的值随时可能发生变化,任何一个中断都有可能修改数据,你post task时所认为task使用的变量,当scheduler真正调用时,可能已经物是人非。

task执行时永远使用当前组件内最新(updated)的变量值,这意味着你在post task时最好想清楚当task执行时所采用的组件变量是否已经发生改变,必要的话需要采取一定保护变量的措施,如设置变量标志位等,如使用send时采用send_busy标志应该是常用的方法。

其他

我看到 TaskBasic 接口里好像有优先级的设定,这意味着如果加入优先级, task 的顺序可能会发生不可控的变化,使用 task 时需要更为细致。

最后

作者水平有限,准确信息请参考TinyOS官方文档

TinyOS 中的 task的更多相关文章

  1. (转).NET 4.5中使用Task.Run和Parallel.For()实现的C# Winform多线程任务及跨线程更新UI控件综合实例

    http://2sharings.com/2014/net-4-5-task-run-parallel-for-winform-cross-multiple-threads-update-ui-dem ...

  2. Ext.Net中的Task控件的使用

    在用到Ext.Net中的Task控件的时候,写了一下基本的使用方法: 控件是在TaskManager里面的Tasks下面的Task 此控件的常用属性有,TaskID.Interval(设置间隔时间). ...

  3. SSIS中Sql Task 获取系统变量

    原文:SSIS中Sql Task 获取系统变量 执行 SQL 任务使用不同的连接类型时,SQL 命令的语法使用不同的参数标记.例如,ADO.NET 连接管理器类型要求 SQL 命令使用格式为 @var ...

  4. Linux中的task,process, thread 简介

    本文的主要目的是介绍在Linux内核中,task,process, thread这3个名字之间的区别和联系.并且和WINDOWS中的相应观念进行比较.如果你已经很清楚了,那么就不用往下看了. LINU ...

  5. Proxmox VE中出现TASK ERROR: command 'apt-get update' failed: exit code 100的解决方法

    问题描述: 出现这个错误一般在WEB或者在Proxmox VE的服务器上面能看到日志: PVE中出现TASK ERROR: command 'apt-get update' failed: exit ...

  6. Android中的task和stack

    今天在重新理了一遍intent的过程中发现task是一个神奇的东西,而它又和stack有着很深的联系.task顾名思义是一个任务,但是这个任务可不一定只是来自一个app,比如我用微信来发一张图片,那么 ...

  7. SV中的task和function

    SV中class的properties和methods默认都是public的,但是可以声明为local和protected. 一个properties声明为local类型的,则只在该class中的me ...

  8. swoole中使用task进程异步的处理耗时任务

    我们知道,swoole中有两大进程,分别是 master 主进程和 manager 管理进程. 其中 master 主进程中会有一个主 reactor 线程和多个 reactor 线程,主要的作用就是 ...

  9. 深入理解gradle中的task

    目录 简介 定义task tasks 集合类 Task 之间的依赖 定义task之间的顺序 给task一些描述 task的条件执行 task rule Finalizer tasks 总结 深入理解g ...

随机推荐

  1. form上传文件2种方式

    示例1: 表单里有图片/文件的上传 <form enctype="multipart/form-data" method="post"> <i ...

  2. l创建Excel文件

    最近的项目中遇到需要将List<Map<String,String>>存储到Excel文件中,为满足此需求设计实现了如下函数: /** * 将MapList转化为Excel文件 ...

  3. JAVA静态代码审查之checkstyle

    技术总监来巡查,刚巧前段时间遇到了一个问题还没解决,就拉着大牛开问.结果,问题是解决了,还附带了另一个问题,或是要求出来,没啥技术含量,但是很麻烦的一个东西:代码格式. 之前我写代码,因为屏幕比较小, ...

  4. csuoj 1116: Kingdoms

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1116 1116: Kingdoms Time Limit: 3 Sec  Memory Limit ...

  5. 最新IP地址数据库 二分逼近&二分查找 高效解析800万大数据之区域分布

    最新IP地址数据库  来自 qqzeng.com 利用二分逼近法(bisection method) ,每秒300多万, 比较高效! 原来的顺序查找算法 效率比较低 readonly string i ...

  6. sql经常会遇到“将截断二进制或字符串”的错误——处理办法

    sql经常会遇到“将截断二进制或字符串”的错误——处理办法 1.修改列长度——无法定位具体字段 2.程序逻辑中增加判断,以定位具体字段 由于我是在报表数据库中直接写SQL,没有校验逻辑,所以想把全部字 ...

  7. LigerUI 表单和表格中的combobox如何初始化值

    摘要: 在修改基础信息的时候,通常会遇到需要修改值为选择值的时候,这时候,数据库存的一般是value,而不是显示的text值,但页面显示的时候如果显示成数字型的值,通常会给人不够直观的感觉.因此,要求 ...

  8. BufferedReader与BufferedWriter读写中文乱码问题

    正常读写英文时用""""没问题 FileReader fre = new FileReader("E:\\TEST\\readText.txt&quo ...

  9. [SQL入门级] 上篇被移出园子首页,那这篇咱就'薄利多销'

    这个系列的博文知识回顾sql知识作的记录,温故而知新.上一篇内容达不到知识分享的层级被移出园子首页,对不住各位看官,内容简单了些.下面咱就记录多一些的基础知识,薄利多销: 控制用户权限 • 创建用户 ...

  10. iOS tableView 滚动后回到顶部

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGPoint contentOffsetPoint = self.tableView ...