本文分析了Contiki OS进程3种状态PROCESS_STATE_NONE
、PROCESS_STATE_RUNNING
、PROCESS_STATE_CALLED
,并给出进程状态转换图。
1. 进程状态概述
Contiki是事件驱动内核,并基于protothread机制提供类线程编程风格(a thread-like programming style),在博文《protothread状态》已介绍了protothread状态,但进程的状态与protothread不尽相同,只有3种状态,如下:
#define PROCESS_STATE_NONE 0
#define PROCESS_STATE_RUNNING 1
#define PROCESS_STATE_CALLED 2
PROCESS_STATE_NONE
是指进程不处于运行状态,而PROCESS_STATE_RUNNING
和PROCESS_STATE_CALLED
都属于运行状态,区别在于:后者确确实实在执行,即获得执行权(被调用了);前者表示就绪状态。进程状态转换图如下,详情见下述分析(visio源文件:进程状态转换图.vsd):
2. PROCESS STATE
2.1 PROCESS_STATE_NONE
进程退出(但此时还没从进程链表删除),先将进程状态设为PROCESS_STATE_NONE
,而后再从进程链表删除,详情见博文《启动一个进程process_start》第四部分exit_process
函数。部分源码如下:
if (process_is_running(p))
{
p->state = PROCESS_STATE_NONE;
process_is_running
函数用于判断进程是否处于运行状态(包括PROCESS_STATE_RUNNING
和PROCESS_STATE_CALLED
),看源码就很清楚了:
int process_is_running(struct process *p)
{
return p->state != PROCESS_STATE_NONE;
}
除此之外,声明一个进程时,进程状态默认也为PROCESS_STATE_NONE
。在博文《实例hello_world剖析》讨论中,宏PROCESS
用于声明一进程函数主体和定义一进程,宏展开如下:
#define PROCESS(name, strname) PROCESS_THREAD(name, ev, data); \
struct process name = { NULL, strname, process_thread_##name }
定义进程name
,只初始化前3个变量,其余的缺省为0,当然也包括进程状态,而PROCESS_STATE_NONE
又被define为0。关于进程结构体可参见博文《主要数据结构之进程》。
2.2 PROCESS_STATE_RUNNING
启动一个进程(由函数process_start
完成),将进程加入进程链表process_list
,而后把进程状态设为PROCESS_STATE_RUNNING
,call_process
函数(真正执行进程主体thread)会根据进程状态决定是否执行进程主体thread,详情见博文《启动一个进程process_start》。即进程获得执行权的时候,先把进程状态设为PROCESS_STATE_RUNNING
,而后再正在执行进程主体thread
。
2.3 PROCESS_STATE_CALLED
在call_process
函数中,在执行进程主体thread
前,先把进程设为PROCESS_STATE_CALLED
,部分源码如下:
if ((p->state &PROCESS_STATE_RUNNING) && p->thread != NULL)
{
process_current = p;
p->state = PROCESS_STATE_CALLED;
ret = p->thread(&p->pt, ev, data);
if (ret == PT_EXITED || ret == PT_ENDED || ev == PROCESS_EVENT_EXIT)
{
exit_process(p, p);
}
else
{
p->state = PROCESS_STATE_RUNNING;
}
}
源代码很少地方用到PROCESS_STATE_CALLED
,表示进程被调用,正在执行。佐证如下:
//call_process函数的部分代码
#if DEBUG
if (p->state == PROCESS_STATE_CALLED)
{
printf("process: process '%s' called again with event %d\n",
PROCESS_NAME_STRING(p), ev);
}
#endif