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 ...
随机推荐
- Molile App(HTTP/HTML)—Analyze Traffic
- C#操作Mongodb的心得
Mongodb是一个强大的文档型数据库,采用BSON的数据格式.本文主要采用其官方的C#驱动来操作其表中的集合.驱动版本为1.1.0,下载地址为: http://mongodb.github.io/m ...
- TIJ——Chapter Eleven:Holding Your Objects
Java Provides a number of ways to hold objects: An array associates numerical indexes to objects. It ...
- 今年暑假不AC
"今年暑假不AC?""是的.""那你干什么呢?""看世界杯呀,笨蛋!""@#$%^&*%...&quo ...
- js隐式转换
JavaScript的数据类型分为六种,分别为null,undefined,boolean,string,number,object.object是引用类型,其它的五种是基本类型或者是原始类型.我们可 ...
- 【皇甫】☀IOC和AOP的拓展实例
<!--构造器注入 --> <bean id="user1" class="cn.happy.entity.User"> <con ...
- HTML5--拖动02-dragstart、drag、dragenter、dragover、dragleave、drop、dragend属性
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- PHP设计模式之:单例模式
前 些日子开始着真正的去了解下设计模式,开始么,简单地从单例模式开始,当然网上看了一些资料,单例模式比较好理解,看看介绍,然后看看代码基本也就能够理 解了,设计模式这些的花点心思基本的是能够理 ...
- 用canvas画环形圆形图片
效果如图自动绘制不停歇 代码如下 var canvas = document.getElementById('myCanvas'),width = canvas.width,height = canv ...
- Base64 的那些事儿
一.Base64是什么? Base64是一种编码的格式.是将信息流(字节流)按照一定的规范,重新组合,显示出完全不相关内容的编码格式. ps.定义是我自己总结的,我觉得对于知识的定义,只要简洁,不错误 ...