contiki 启动进程 process_start

来源:互联网 发布:linux 打开本地目录 编辑:程序博客网 时间:2024/06/05 02:48
contiki 所有进程都必须调用 process_start()函数,才能运行起来。系统初始化的时候, process_start(&etimer_process, NULL);必须显示的启动时间进程,这个函数调用后,就会启动本线程。

那用户自己的进程呢,有些进程是需要手动的启动起来(至于其他进程,等还没搞清楚),需要自动运行的程序要添加到struct process * const autostart_processes[];这个数组里面,然后在主程序候总调用autostart_start(autostart_processes);就可以把将这些进程自动的启动,比如

AUTOSTART_PROCESSES(&print_hello_process,&print_world_process);

下面是autostart_start函数,它就是讲存放在全局变量autostart_process[]里面的所有进程调用process_start 函数,依次启动起来。

autostart_start(struct process * const processes[])
{
int i;

for(i = 0; processes[i] != NULL; ++i) {
process_start(processes[i], NULL);
PRINTF("autostart_start: starting process '%s'\n", processes[i]->name);
}
}

下面是process_start函数:

process_start所干的工作就是:

1.先把将要执行的进程加入到进程队列process_list的首部,如果这个进程已经在process_list中,就return;
2.接下来就把state设置为PROCESS_STATE_RUNNING并且初始化pt的lc为0(这一步初始化很重要,关系到protothread进程模型的理解)。
3.最后通过函数process_post_synch()给进程传递一个PROCESS_EVENT_INIT事件,让其开始执行,看看这个函数的定义:

void
process_start(struct process *p, const char *arg)
{
struct process *q;

/* First make sure that we don't try to start a process that is
already running. */
for(q = process_list; q != p && q != NULL; q = q->next);


/* If we found the process on the process list, we bail out. */

if(q == p) {

return;

}

/* Put on the procs list.*/

p->next = process_list;

process_list = p;

p->state = PROCESS_STATE_RUNNING;

PT_INIT(&p->pt);


PRINTF("process: starting '%s'\n", p->name);


/* Post a synchronous initialization event to the process. */

process_post_synch(p, PROCESS_EVENT_INIT, (process_data_t)arg);

}

上面process_start最后调用了process_post_synch()这个函数是同步投递函数的,也就是事件投递过去,另外一个进程就要运行起来。下面是process_process_post_synch()的实现部分,由于process_current 是全局变量,指向当前正在运行的进程,此时,process_current将会指向你传递过来的进程。而你传递过来的进程可能会退出或者被挂起等待一个事件,而如果它没有引起新的进程运行,那么系统要知道谁调用的此进程,然后返回到老的 process_current 让系统继续运行下去,所以,这里必须要保存当前的process_current,所以用临时变量记录 *caller,记录了下来。

void

process_post_synch(struct process *p, process_event_t ev, process_data_t data)

{

struct process *caller = process_current;

call_process(p, ev, data);

process_current = caller;

}

将时间使用 process_post_synch 投递后,真正启动进程的操作是由call_process来完成的。下面是call_process 的代码:

假如进程process的状态是PROCESS_STATE_RUNNING以及进程中的thread函数不为空的话,就执行这个进程:
1.首先把process_current指向p;
2.接着把process的state改为PROCESS_STATE_CALLED;
3.执行hello_world这个进程的body也就是函数p->thread,并将返回值保存在ret中,如果返回值表示退出或者遇到了PROCESS_EVENT_EXIT的时事件后,便执行exit_process()函数,process退出。不然程序就应该在挂起等待事件的状态,那么就继续把p的状态维持为PROCESS_STATE_RUNNING。

static void

call_process(struct process *p, process_event_t ev, process_data_t data)

{

int ret;


#if DEBUG

if(p->state == PROCESS_STATE_CALLED) {

printf("process: process '%s' called again with event %d\n", p->name, ev);

}

#endif /* DEBUG */


if((p->state & PROCESS_STATE_RUNNING) &&

p->thread != NULL) {

PRINTF("process: calling process '%s' with event %d\n", p->name, ev);

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;

}

}

}

在call_process里面由引入了一个exit_process()函数;

static void

exit_process(struct process *p, struct process *fromprocess)

{

register struct process *q;

struct process *old_current = process_current;


PRINTF("process: exit_process '%s'\n", p->name);


if(process_is_running(p)) {

/* Process was running */

p->state = PROCESS_STATE_NONE;


/*

* Post a synchronous event to all processes to inform them that

* this process is about to exit. This will allow services to

* deallocate state associated with this process.

*/

for(q = process_list; q != NULL; q = q->next) {//向所有的进程发送退出事件,其他进程会根据此时间标志,进行一些相关的处理,比如要退出的进程使用了etimer事件,etimer_process就会查找timerlist看看哪个timer是与这个进程相关的,就把它从timerlist中清除

if(p != q) {


call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p);

}

}


if(p->thread != NULL && p != fromprocess) { //向要退出的进程发送事件,前提是,要退出的进程不能使当前运行的进程。可能是A进程要求B进程退出,此时A进程要向B进程发送一个事件,因为B进程可能希望在自己退出的时候,再执行一些操作。类似与 钩子函数 或者 析构函数?

/* Post the exit event to the process that is about to exit. */

process_current = p;

p->thread(&p->pt, PROCESS_EVENT_EXIT, NULL);

}

}


if(p == process_list) {

process_list = process_list->next;

} else {

for(q = process_list; q != NULL; q = q->next) {

if(q->next == p) {


q->next = p->next;


break;

}

}

}


process_current = old_current;

}

exit_process函数有两个参数,前一个是要退出的process,后一个是当前的process。
在这个进程要退出之前,必须要给所有的进程都要发送一个PROCESS_EVENT_EXITED事件,告诉所有与之相关的进程它要走了,如果收到这个事件的进程与要死的进程有关的话,自然会做出相应的处理(一个典型的例子是,如果一个程序要退出的话,就会给etimer_process进程发送一个PROCESS_EVENT_EXITED事件,那么收到这个事件之后,etimer_process就会查找timerlist看看哪个timer是与这个进程相关的,就把它从timerlist中清除)。

如果要退出的process就是当前的process,那么就只需要把它从进程列表中清除即可;如果要退出的process不是当前的process,那么当前的process就要给要退出的process传递一个PROCESS_EVENT_EXIT事件让其进程的body退出,然后再将其从进程列表中清除。

引用贴:

http://blog.chinaunix.net/uid-9112803-id-2891328.html


http://www.smeshlink.com/contiki/forum.php?mod=viewthread&tid=275&extra=page%3D1

http://www.contikistudio.com/forum.php?mod=viewthread&tid=274&extra=page%3D1

0 0