2 Protothreads简介
Protothrcads是由瑞典计算机科学研究所的科学家Adam Dunkels所创的一种新的线程编程方法。按AdamDunkels所说,Protothreads是专为资源紧张的系统设计的一种耗费资源少,且不使用堆栈的线程模型,它可以不使用复杂的状态机机制来实现顺序流的控制。Proto—thrcads也可以用于操作系统当中。
简单地说,Protothrcads借鉴了用c语言实现协同(co—routine)的原理,它应用switch—case语句的直接跳转功能,实现了有条件阻塞(conditional block),最终实现了虚拟的并行处理功能(concurrent)。实际上,Protothrcads并不是真正的线程,在多任务的切换中并不会真正涉及上下文的切换,其线程的调度也仅仅是依靠隐式的return,进而退出函数体来完成的。但是Protothreads的优点却是实实在在的。首先它不需要堆栈空间,而正如笔者用宏实现的那样,Protothrcads也实现了很多只有线程编程方法才能实现的机制,比如阻塞。而用宏进行了封装之后,使用者完全可以像使用线程一样使用它们,而且其逻辑更加简化,这大大增加了程序的清晰度,并降低了开发维护的难度。
在对实时性要求比较高或者说要求并行处理的场合,往往需要在任务A执行到一定程度、等待事件C发生时,退出当前任务A并转而执行任务B;当事件C发生之后,系统继续回到任务A,继续方才的执行。所以必须将任务A上次执行到地方的环境存储起来,以便重回任务A后可以接着打断的地方继续运行。线程的上下文切换可以达到这个目的,Simon Tatham用C语言实现的co—routine也可以。Protothreads正是借鉴了这一原理,如以下任务函数所示:
可以看出,在进行了宏扩展之后,下面的程序段和上面的程序段是完全相同的,但是宏封装很好地构建了一个上层的逻辑体系。这正是Protothreads的核心所在。同时,这也决定了Protothreads具有一定的局限:
①Protothreads中使用的必须是静态变量或者全局变量;
②避免与switch语句的合用(Protothreads的实现已经用了switch语句);
③因为编译器会将__LINE__解释为当前所在的行号,所以不能将多个“返回”置于同一行。
3 调度器设计
时间触发方式的嵌入式系统是根据定时器产生的恒定间隔的中断来触发和管理任务的。系统依靠一个基准的时间中断,以此中断为任务处理的节奏和“节拍”,任务的调度发生在“节拍”规定的时刻。中断服务子程序也同样占用这个时间间隔,为了系统的稳定性,一方面要使中断服务子程序尽可能短,以节省任务的执行时间;另一方面,执行的任务也应该尽可能短,一些比较耗时的任务可以细分为若干个子任务加以调度。同时,这也要求调度器的设计尽可能简单。本文的设计思想就是对于系统仅仅定义一个任务控制块(TCB)队列,每个任务对应于队列中的一个节点,由中断服务子程序更改TCB队列中的记录,调度函数根据此TCB来进行调度。可以略微修改Proto—threads中的结构体pt,以满足作为TCB队列节点的需要。当然,此结构也需要声明为全局变量或者静态变量。其数据结构如下所示: