Contiki系统关于PROCESS_CONTEXT_BEGIN与PROCESS_CONTEXT_END见解
来源:互联网 发布:电脑连接的常用端口 编辑:程序博客网 时间:2024/06/14 23:35
在阅读socket源码时有PROCESS_CONTEXT_BEGIN与PROCESS_CONTEXT_END的使用。字面意思是切换上下文,但是个人的理解,在其他操作系统切换上下文是指进出栈保存的。很明显contiki是不具备这功能的,因此很很疑惑他的作用。网上搜索了一下也没有关于此系统宏的解析,由此写下这一篇,用于记录。
以下是源码中对于PROCESS_CONTEXT_BEGIN、PROCESS_CONTEXT_END的注释。
/** * Switch context to another process * * This function switch context to the specified process and executes * the code as if run by that process. Typical use of this function is * to switch context in services, called by other processes. Each * PROCESS_CONTEXT_BEGIN() must be followed by the * PROCESS_CONTEXT_END() macro to end the context switch. * * Example: \code PROCESS_CONTEXT_BEGIN(&test_process); etimer_set(&timer, CLOCK_SECOND); PROCESS_CONTEXT_END(&test_process); \endcode * * \param p The process to use as context * * \sa PROCESS_CONTEXT_END() * \sa PROCESS_CURRENT() */
对注释Example展开可以得到以下源码,作用是保存了当前系统指针,并把需要调用的进程指针指向当前指针,然后执行etimer_set函数。
PROCESS_CONTEXT_BEGIN(&test_process); etimer_set(&timer, CLOCK_SECOND); PROCESS_CONTEXT_END(&test_process);//展开如下{struct process *tmp_current = PROCESS_CURRENT();process_current = &test_process;etimer_set(&timer, CLOCK_SECOND);process_current = tmp_current;}
注释上写明是调用服务时需要这样做,那么疑问是为什么需要这样做呢?
查看etimer_set源码,发现其调用的add_timer函数会把当前的进程指针PROCESS_CURRENT()存到定时器的结构体中。因此,如果在一个进程中调用其他进程的服务函数将会导致进程指针不对而不起作用,甚至跑飞。
static voidadd_timer(struct etimer *timer){ struct etimer *t; etimer_request_poll(); if(timer->p != PROCESS_NONE) { for(t = timerlist; t != NULL; t = t->next) { if(t == timer) { /* Timer already on list, bail out. */ timer->p = PROCESS_CURRENT(); update_time(); return; } } } /* Timer not on list. */ timer->p = PROCESS_CURRENT(); timer->next = timerlist; timerlist = timer; update_time();}
下面为ubuntu下仿真的代码,测试了几个方面的系统操作,1、hello_world_process线程的挂起;2、context_process本篇的重点,PROCESS_CONTEXT_BEGIN和PROCESS_CONTEXT_END的使用;3、test_process进程,etimer的使用和对其他进程的触发。
#include "contiki.h"#include <stdio.h> /* For printf() *//*---------------------------------------------------------------------------*/PROCESS(hello_world_process, "Hello world process");/*---------------------------------------------------------------------------*/PROCESS_THREAD(hello_world_process, ev, data){static struct etimer et; PROCESS_BEGIN(); while(1) { printf("Hello, world\n"); PROCESS_WAIT_EVENT(); etimer_set(&et, CLOCK_SECOND*2); printf("hold 1\n"); PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_POLL || ev == PROCESS_EVENT_TIMER); printf("hold 2\n"); PROCESS_WAIT_EVENT(); } PROCESS_END();}static struct etimer het;/*---------------------------------------------------------------------------*/PROCESS(context_process, "contextprocess");/*---------------------------------------------------------------------------*/PROCESS_THREAD(context_process, ev, data){ PROCESS_BEGIN(); while(1) { printf("context\n"); PROCESS_WAIT_EVENT_UNTIL( ev == PROCESS_EVENT_TIMER); } PROCESS_END();}/*---------------------------------------------------------------------------*//*---------------------------------------------------------------------------*/PROCESS(test_process, "test process");AUTOSTART_PROCESSES(&test_process);/*---------------------------------------------------------------------------*/PROCESS_THREAD(test_process, ev, data){ static struct etimer et; static int cnt= 0; PROCESS_BEGIN(); etimer_set(&et, CLOCK_SECOND); process_start(&hello_world_process,0); process_start(&context_process,0); while(1) { PROCESS_WAIT_EVENT_UNTIL( ev == PROCESS_EVENT_TIMER); etimer_set(&et, CLOCK_SECOND); cnt++; if(cnt>5) { cnt =0; process_poll(&hello_world_process); } else { printf("%d:",clock_time()); printf("test, world\n"); PROCESS_CONTEXT_BEGIN(&context_process); etimer_set(&het, CLOCK_SECOND*1); PROCESS_CONTEXT_END(&context_process); } } PROCESS_END();}/*---------------------------------------------------------------------------*/
代码运行结果如下:
Contiki 3.x started with IPV6, RPL
Rime started with address 1.2.3.4.5.6.7.8
MAC nullmac RDC nullrdc NETWORK sicslowpan
Tentative link-local IPv6 address fe80:0000:0000:0000:0302:0304:0506:0708
Hello, world
context
1793399050:test, world
context
1793400051:test, world
context
1793401051:test, world
context
1793402052:test, world
context
1793403053:test, world
context
hold 1
1793405054:test, world
1793406054:test, world
1793407054:test, world
context
context
1793408056:test, world
假如对test_process代码进行如下注释:
//PROCESS_CONTEXT_BEGIN(&context_process); etimer_set(&het, CLOCK_SECOND*1); //PROCESS_CONTEXT_END(&context_process);
得到的输出结果如下:
Contiki 3.x started with IPV6, RPL
Rime started with address 1.2.3.4.5.6.7.8
MAC nullmac RDC nullrdc NETWORK sicslowpan
Tentative link-local IPv6 address fe80:0000:0000:0000:0302:0304:0506:0708
Hello, world
context
1793689078:test, world
1793690079:test, world
1793690080:test, world
1793691081:test, world
1793691081:test, world
hold 1
1793692081:test, world
1793693082:test, world
1793693084:test, world
hold 2
1793694084:test, world
1793694085:test, world
Hello, world
1793695085:test, world
1793696085:test, world
1793696085:test, world
1793697085:test, world
1793697085:test, world
hold 1
1793698087:test, world
1793699087:test, world
1793699088:test, world
结果表明,context_process并没有被触发,因为etimer het得到得进程指针并不是context_process指针,系统服务进程etiemr没有post事件给context_process。
PROCESS_CONTEXT_BEGIN和PROCESS_CONTEXT_END的使用场景,应该是在运行一个进程时,想对另外一个进程进行一些系统服务操作,如etimer、ctimer等定时器的操作,改变他的参数。
- Contiki系统关于PROCESS_CONTEXT_BEGIN与PROCESS_CONTEXT_END见解
- cc2530-关于Contiki系统的时钟
- 关于做系统的一些见解
- 关于STM32系统框架的一点见解
- Contiki开发3:调试平台与Debug系统
- 关于建模与编程的一些见解
- Contiki 系统框架
- contiki系统学习套件
- 入门基础Contiki OS与Instant Contiki
- contiki与ucos
- Contiki与IoT
- 关于系统的高可用性的一些见解
- Contiki开发6:shell系统
- contiki中关于进程的开始与挂起等相关函数的说明与小结
- 关于生产者与消费者的同步锁的个人见解
- 关于绑定IP地址与端口号的见解
- 关于绑定IP地址与端口号的见解
- 关于向上转型与向下转型的一点个人见解
- linux下的EDA——DC使用
- 二叉树的七种遍历方式以及按行打印
- Gym
- 百练4982 踩方格
- linux复习之进程基础知识
- Contiki系统关于PROCESS_CONTEXT_BEGIN与PROCESS_CONTEXT_END见解
- H.264句法语义学习
- IO流与多线程
- 【bzoj3524】 [Poi2014]Couriers
- TCP四次挥手中的TIME_WAIT状态存在的理由
- 集合与泛型
- 树的直径
- 瓜田李下
- 文件压缩和归档