Contiki-一个进程的例子
进程调度器
进程调度器的作用是调用进程。进程调度器通过调用实现进程线程的函数来调用进程。Contiki中所有的进程被设计为响应传递到进程中的事件,或者相应进程请求的轮询。进程调度器在调度进程的时候会将事件标识符和一个不透明指针传递到进程中,该指针由进程调用者提供,可以设置为NULL(该事件不需要传递数据)。当进程轮询时,不会传递数据。
开始进程
/**
* Start a process.
*
* \param p A pointer to a process structure.
*
* \param arg An argument pointer that can be passed to the new
* process
*
*/
CCIF void process_start(struct process *p, const char *arg);
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", PROCESS_NAME_STRING(p)); /* Post a synchronous initialization event to the process. */
process_post_synch(p, PROCESS_EVENT_INIT, (process_data_t)arg);
}
process_start()开始一个进程。该函数的目的是设置进程控制块,将进程加入到内核有效进程链表中,然后调用进程线程中的初始化代码。最后给该进程发送一个同步的初始化事件。process_start()被调用后,该进程就开始运行了。
process_start()函数先做一个明智的检查,检查是否该进程已经存在进程链表中。如果是,表明该进程已经被运行了,process_start()函数直接返回。在确认该进程没有开始运行后,内核将该进程加入到链表中,并设置进程控制块。进程的状态被设置为PROCESS_STATE_RUNNING,进程的线程被PT_INIT()初始化。最后,内核为进程发送给一个同步事件PROCESS_EVENT_INIT,且传递一个不透明指针给进程,该指针是由调用process_start()的进程传入的,用于传递给要运行的进程一些信息。不过,这个指针一般都设为NULL。当进程接收到它的第一个事件PROCESS_EVENT_INIT,进程将执行该进程线程的第一部分。通常,这部分包含进程开始时即将运行的初始化代码。
退出进程和杀死进程
进程退出有两种方法:进程自动退出和被其它进程杀死。调用函数process_exit()或者当进程线程执行到PROCESS_END()语句时,进程将退出。
进程可以调用函数process_exit()杀死另一个进程。
当一个进程退出(无论是主动退出还是被动退出),Contiki内核会发送给一个事件通知其它进程,这可以让其它进程释放退出进程所占有的资源。事件PROCESS_EVENT_EXITED将会被以同步事件的方式发送到其它所有进程。
当一个被另一个金曾杀死时,被杀的进程将会接收到同步事件PROCESS_EVENT_EXIT,该事件通知将要被杀死的进程和能够释放已分配资源的进程,或者其它将要退出的进程。
在Contiki内核发送事件通知将要退出的进程后,将从进程链表中删除该进程。
自启动进程
Contiki提供了一个机制,在系统启动时,或者包含进程的模块被加载时,自动运行进程。该机制由自启动模块实现。该机制能够让模块开发者告知系统该模块中包含什么进程。当模块从内存中移除时,也能让系统做相应的处理。
自启动进程保存在一个链表中,自启动模块利用该链表实现自动运行进程。进程启动的顺序与它在链表中的顺序一致。
自启动进程有两种时机:系统启动时和模块被加载时。所有需要在系统启动时自启动的进程必须被包含在一个单一的系统级的链表中。这个自启动链表由用户提供,且一般在一个用户模块中。当这个模块被用作可加载模块时,链表能够让系统知道模块被加载时需要运行什么进程。
当加载一个模块时,模块加载器将查找自启动进程链表,并在模块被加载到内存后启动链表中的进程。当模块将要被卸载时,模块加载器利用该链表杀死在模块加载时启动的进程。
一个接收事件并打印其数字的进程的例子:
#include "contiki.h" PROCESS(example_process, "Example process");
AUTOSTART_PROCESSES(&example_process); PROCESS_THREAD(example_process, ev, data)
{
PROCESS_BEGIN(); while() {
PROCESS_WAIT_EVENT();
printf("Got event number %d\n", ev);
} PROCESS_END();
}
上面的代码是一个Contiki完整的进程。该进程被申明、定义和自动运行。
第三行,我们定义了进程控制块。进程控制块定义了进程控制块的名字example_process和文本的、用户可读的进程名字Example process。在定义了进程控制块后,我们可以在其它表达式中使用该变量名。
第四行,语句AUTOSTART_PROCESSES()告诉Contiki在系统启动时自动启动进程example_process。自启动链表由指向进程控制块的指针组成,所以需要在变量example_process前加&取地址符。
第六行,我们定义了进程线程。它包含了进程的变量名example_process和传递事件的变量ev及数据data。
第八行,我们使用了PROCESS_BEGIN()定义了一个进程的开始。该定义标志进程线程的开始。在进程每次被调度运行的时候,该申明语句上面的代码都会运行。在大多数情形下,你不需要在PROCESS_BEGIN()之上放任何代码。
第十行,开始进程的主循环。Contiki进程不能包含永不结束的死循环。但是在上面代码中,这样的死循环是安全的,因为进程将会等待时间。当一个Contiki进程在等待事件时,它会将控制器返回给Contiki内核。在该进程等待期间,内核将会为其它进程提供服务。
第十一行,进程等待事件的发生。表达式PROCESS_WAIT_EVENT()将返回控制权给Contiki内核,并等待内核传递事件到该进程。当Contiki内核传递事件给该进程后,PROCESS_WAIT_EVENT()后面的代码将被执行。在进程被唤醒后,将执行第十二行的打印语句。这一行的作用是打印进程接收到的事件编号。如果同时传入 了一个指针,该指针变量就是data(?)。
第十五行,PROCESS_END()标识进程的结束。每个Contiki进程必须包含PROCESS_BEGIN()和PROCESS_END()。当执行到PROCESS_END()时,该进程自动退出,并从内核中的进程链表中移除。不过,由于存在死循环,永远不会执行到PROCESS_END()。只有系统被关掉、或者该进程被process_exit()杀死的时候才会被停止运行。
一个启动进程并发送事件的函数
static char msg[] = "Data"; static void
example_function(void)
{
/* Start "Example process", and send it a NULL
pointer. */ process_start(&example_process, NULL); /* Send the PROCESS_EVENT_MSG event synchronously to
"Example process", with a pointer to the message in the
array 'msg'. */
process_post_synch(&example_process,
PROCESS_EVENT_CONTINUE, msg); /* Send the PROCESS_EVENT_MSG event asynchronously to
"Example process", with a pointer to the message in the
array 'msg'. */
process_post(&example_process,
PROCESS_EVENT_CONTINUE, msg); /* Poll "Example process". */
process_poll(&example_process);
}
两个进程间通过事件完成交互。上面的例子中的函数启动了一个进程,并向它发送一个同步事件和轮询请求。
总结
进程通过发送事件实现与其它进程通信。
摘录自:http://blog.csdn.net/tidyjiang/article/details/51378589
Contiki-一个进程的例子的更多相关文章
- 让powershell同时只能运行一个脚本(进程互斥例子)
powershell,mutex,互斥,进程互斥,脚本互斥 powershell脚本互斥例子,在powershell类别文章中,声明原创唯一. powershell 传教士 原创文章 2016-07- ...
- Erlang 进程被抢占的条件——一个进程长时霸占调度器的极端示例
最近研究 binary 的实现和各种操作对应的 beam 虚拟机汇编指令,发现有一些指令序列是不可重入的,比如说有的指令构造一个上下文(也就是某种全局状态),然后下一条指令会对这个上下文做操作(具体的 ...
- JAVA调用系统命令或可执行程序--返回一个Runtime运行时对象,然后启动另外一个进程来执行命令
通过 java.lang.Runtime 类可以方便的调用操作系统命令,或者一个可执行程序,下面的小例子我在windows和linux分别测试过,都通过.基本原理是,首先通过 Runtime.getR ...
- 一个UWSGI的例子
摘要:uwsgi执行顺序:启动master进程,执行python脚本的公共代码(import同一层).然后生成worker进程,uwsgi.post_fork_hook=init_functions, ...
- 网络编程基础【day10】:我是一个进程(三)
本节内容 1.引子 2.进程的诞生 3.线程 4.争吵 一.引子 我听说我的祖先们生活在专用计算机里, 一生只帮助人类做一件事情,比说微积分运算 了.人口统计了 .生成密码.甚至通过织布机印花 ! ...
- 一个进程间同步和通讯的 C# 框架
转自原文 一个进程间同步和通讯的 C# 框架 threadmsg_demo.zip ~ 41KB 下载 threadmsg_src.zip ~ 65KB 下载 0.背景简介 微软在 .NE ...
- Linux内核中的信号机制--一个简单的例子【转】
本文转载自:http://blog.csdn.net/ce123_zhouwei/article/details/8562958 Linux内核中的信号机制--一个简单的例子 Author:ce123 ...
- Qt 进程和线程之一:运行一个进程和进程间通信
Qt提供了对进程和线程的支持.本节讲述了怎样在Qt应用程序中启动一个进程,以及几种常用的进程间通信方法.如果对进程和线程的概念不是很了解,可以看我的另一篇博客:[多进程和多线程的概念. 设计应用程序时 ...
- C# 最基本的涉及模式(单例模式) C#种死锁:事务(进程 ID 112)与另一个进程被死锁在 锁 | 通信缓冲区 资源上,并且已被选作死锁牺牲品。请重新运行该事务,解决方案: C#关闭应用程序时如何关闭子线程 C#中 ThreadStart和ParameterizedThreadStart区别
C# 最基本的涉及模式(单例模式) //密封,保证不能继承 public sealed class Xiaohouye { //私有的构造函数,保证外部不能实例化 private ...
随机推荐
- python for mysql
# -*- coding: utf-8 -*- '''python coded by written in 2016/8/31 Used for get win os log for each win ...
- Java连接SqlServer2008数据库(转)
Java连接SqlServer2008数据库 首先下载JDBC:下载地址:http://www.microsoft.com/zh-cn/download/details.aspx?id=21599 下 ...
- Spring学习笔记之二----基于XML的Spring AOP配置
在Spring配置文件中,通常使用<aop:config>元素来设置AOP,其中应包括: <aop:aspect>指定aspect,aspect是一个POJO类,包含了很多的a ...
- C语言 01 形参实参
之前的都在印象笔记记录 continue 结束本轮循环体,进入下一次循环.break 直接结束整个while循环 形参:定时函数时函数名后面中的参数实参:调用函数时传入的具体数据基本数据类型作为形参, ...
- Css、javascript、dom(一)
一:Css 1.1:position定义和用法 position 属性规定元素的定位类型. 可能的值 值 描述 absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定 ...
- MessageReceiver
class MessageReceiver { private RelayEngine<MessageCollection> _MessageRelayEngine; private st ...
- poj3069 Saruman's Army
http://poj.org/problem?id=3069 Saruman the White must lead his army along a straight path from Iseng ...
- 【转】eclipse 创建struts2
转载地址:http://blog.163.com/sean_zwx/blog/static/169032755201091595558378/ 今天我用Ecipse搭建Struts框架,并且使用Str ...
- div嵌套导致子区域margin-top失效不起作用的解决方法
有两个嵌套关系的div,如果外层div的父元素padding值为0, 那么内层div的margin-top或者margin-bottom的值会"转移"给外层div,使父元素产生上外 ...
- 第七章 Hibernate性能优化
一对一关联 实体类关系 一对多 多对多 一对一 Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射.下面以员工账号和员工档案表为例,介绍这两种映射方式,并使用这两种映射方 ...