TinyOS 中的 task
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的更多相关文章
- (转).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 ...
- Ext.Net中的Task控件的使用
在用到Ext.Net中的Task控件的时候,写了一下基本的使用方法: 控件是在TaskManager里面的Tasks下面的Task 此控件的常用属性有,TaskID.Interval(设置间隔时间). ...
- SSIS中Sql Task 获取系统变量
原文:SSIS中Sql Task 获取系统变量 执行 SQL 任务使用不同的连接类型时,SQL 命令的语法使用不同的参数标记.例如,ADO.NET 连接管理器类型要求 SQL 命令使用格式为 @var ...
- Linux中的task,process, thread 简介
本文的主要目的是介绍在Linux内核中,task,process, thread这3个名字之间的区别和联系.并且和WINDOWS中的相应观念进行比较.如果你已经很清楚了,那么就不用往下看了. LINU ...
- Proxmox VE中出现TASK ERROR: command 'apt-get update' failed: exit code 100的解决方法
问题描述: 出现这个错误一般在WEB或者在Proxmox VE的服务器上面能看到日志: PVE中出现TASK ERROR: command 'apt-get update' failed: exit ...
- Android中的task和stack
今天在重新理了一遍intent的过程中发现task是一个神奇的东西,而它又和stack有着很深的联系.task顾名思义是一个任务,但是这个任务可不一定只是来自一个app,比如我用微信来发一张图片,那么 ...
- SV中的task和function
SV中class的properties和methods默认都是public的,但是可以声明为local和protected. 一个properties声明为local类型的,则只在该class中的me ...
- swoole中使用task进程异步的处理耗时任务
我们知道,swoole中有两大进程,分别是 master 主进程和 manager 管理进程. 其中 master 主进程中会有一个主 reactor 线程和多个 reactor 线程,主要的作用就是 ...
- 深入理解gradle中的task
目录 简介 定义task tasks 集合类 Task 之间的依赖 定义task之间的顺序 给task一些描述 task的条件执行 task rule Finalizer tasks 总结 深入理解g ...
随机推荐
- CentOS 6.2 SVN搭建 (YUM安装)
安装说明 安装了一下SVN服务器,本文没有与Apache整合,过程如下: 系统环境:CentOS-6.2安装方式:yum install (源码安装容易产生版本兼容的问题)安装软件:系统自动下载SVN ...
- JdbcUtils.java
package com.jdbc.dbutils; import java.lang.reflect.Field; import java.sql.Connection; import java.sq ...
- HTML的<object>标签 (转)
object标签用于定义一个嵌入的对象,包括:图像.音频.Java applets.ActiveX.PDF以及Flash.该标签允许您规定插入HTML文档中的对象的数据和参数,以及可用来显示和操作数据 ...
- 源代码编译安装Python3.5.2
由于没有找到Python3.5的rpm安装包,因此进行源代码编译安装 1.下载Python3.5.2 [root@seastar ~]# cd /usr/local/src [root@seastar ...
- 【原创】我所理解的自动更新-外网web服务器配置
ClientDownload和ClientUpdate共享渠道配置信息: channel-0.php //以appstore的渠道为例 <?php define('APPNAME', 'TOKE ...
- JSON对象长度和遍历方法
摘自博客 (http://caibaojian.com/json-length.html) 原文链接:http://caibaojian.com/json-length.html JSON数组有长度j ...
- dev GridControl实现拖拽
一.示例说明 以gridControl1和gridControl2为例,从gridControl1拖拽行到gridControl2中去. 二.属性设置 gridControl2.AllowDrop = ...
- lua定义一个简单的类
classA.lua: classA = { a = , b = , --__index = classA; }; classA.__index = classA; function classA:n ...
- 教你轻松计算AOE网关键路径(转)
原文链接:http://blog.csdn.net/wang379275614/article/details/13990163 本次结合系统分析师-运筹方法-网络规划技术-关键路径章节,对原文链接描 ...
- linux问题
make:进入目录'/opt/FriendlyARM/tiny4412/05android/android-4.1.2'target Dex: framework trouble writing ou ...