CC2538之Contiki3.0实验:2-PROCESS 你永远不懂阅读C代码的伤悲

来源:互联网 发布:婚纱照相册排版软件 编辑:程序博客网 时间:2024/04/30 21:14

相信不少朋友在学习Contiki查阅了不少帖子和资料,但是我只能说一句,貌似没多大用啊,看了很多的帖子发现还是理解不了Contiki的设计;真心很麻烦的东东,本科生们就更加痛苦了,这个OS是这么麻烦,为什么这么说呢,没记错我本科的时候的C语言基本知识就是会点结构体;也许时代进步很多学生的专业知识很扎实!回想一下TinyOS,代码的阅读是那么舒心,整个代码也根本谈不上OS,任务本质就是对Task函数按照序号一次分配一个全局ID,从0开始;POST在全局的sheude数组元素中存下ID号,POLL执行取出ID号,然后调用SWITCH(ID);case下面是ID号对应的函数,代码分析简单;看不懂nesC也可以通过转成app.c后从main函数查看任务是怎样调度的;Contiki对于新手则不像TinyOS那么简单,C语言的技巧应用的淋漓尽致;C不过关的朋友们可以正好充电;

下面还是就先前第一个例程开始阅读代码;test_null.c中:

1,PROCESS(test_null, "我是菜鸟");  

core/sys/process.h中定义:
#if PROCESS_CONF_NO_PROCESS_NAMES#define PROCESS(name, strname)\  PROCESS_THREAD(name, ev, data);\  struct process name = { NULL,        \                          process_thread_##name }#else#define PROCESS(name, strname)\  PROCESS_THREAD(name, ev, data);\  struct process name = { NULL, strname,\                          process_thread_##name }#endif
struct process {  struct process *next;#if PROCESS_CONF_NO_PROCESS_NAMES#define PROCESS_NAME_STRING(process) ""#else  const char *name;#define PROCESS_NAME_STRING(process) (process)->name#endif  PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));  struct pt pt;  unsigned char state, needspoll;};

2,PROCESS_THREAD(test_null, ev, data) 
core/sys/process.h中定义:
#define PROCESS_THREAD(name, ev, data) \static PT_THREAD(process_thread_##name(struct pt *process_pt,\       process_event_t ev,\       process_data_t data))

现在咱们需要看的是PT_THREAD宏定义了:(core/sys/pt.h)
#define PT_THREAD(name_args) char name_args

上面展开
static char process_thread_##name(struct pt *process_pt,\       process_event_t ev,\       process_data_t data)

好了,现在我们清楚了这些玩意的意思,当然我就不分析了,大家在使用Contiki之前必须是C语言功底深厚

不清楚的朋友提示一下函数指针;

            

3,AUTOSTART_PROCESSES(&test_null); 

core/sys/autostart.h文件中定义:

#if ! CC_NO_VA_ARGS#if AUTOSTART_ENABLE#define AUTOSTART_PROCESSES(...)\struct process * const autostart_processes[] = {__VA_ARGS__, NULL}#else /* AUTOSTART_ENABLE */#define AUTOSTART_PROCESSES(...)\extern int _dummy#endif /* AUTOSTART_ENABLE */#else#error "C compiler must support __VA_ARGS__ macro"#endif

在contiki_main中调用:
autostart_start(autostart_processes);

看一下core/sys/autostart.c:
voidautostart_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);  }}


4,现在让我们来看一下,
PROCESS_BEGIN(); 
根据core/sys/process.h 

#define PROCESS_BEGIN()             PT_BEGIN(process_pt)
根据core/sys/pt.h
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} LC_RESUME((pt)->lc)
core/sys/lc.h中
#define LC_RESUME(lc)
简写成
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} (pt)->lc

注意符号'{'

PROCESS_END();
根据core/sys/process.h 

#define PROCESS_END()               PT_END(process_pt)
根据core/sys/pt.h
#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \                   PT_INIT(pt); return PT_ENDED; }

#define PT_INIT(pt)   LC_INIT((pt)->lc)    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">           </span>
core/sys/lc.h中
#define LC_END(lc)#define LC_INIT(lc)

和上面的注意一样是符号‘}’
呵呵,不多说了,大家应该清楚这两个玩意应该是配合使用了


更多的WAIT,YIELD,WAITWHILE,EXIT,不做介绍,代码的阅读真心累人,朋友们可以自己去阅读代码
这是没有办法的事情,没有文档能够说清楚它的设计思想,最好是自己去理解!


5,通过contiki-main.c文件,查看int main(void)函数,简化一下main函数,去除烦人的代码

intmain(void){  //省去初始化  process_init();  process_start(&etimer_process, NULL);  ctimer_init();#if NETSTACK_CONF_WITH_IPV6  memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));  queuebuf_init();  process_start(&tcpip_process, NULL);#endif /* NETSTACK_CONF_WITH_IPV6 */  process_start(&sensors_process, NULL);  autostart_start(autostart_processes);  while(1) {      process_run();  }}

比较重要的函数就是
process_init();
process_start(...);
ctimer_init();
queuebuf_init();
autostart_start(autostart_processes);
process_run();



先抛开
queuebuf_init(以后必须学习,至少也应该提供内存的申请使用和释放)
ctimer_init();这些
剩下
process_init();

core/sys/process.c中

voidprocess_init(void){  lastevent = PROCESS_EVENT_MAX;  nevents = fevent = 0;#if PROCESS_CONF_STATS  process_maxevents = 0;#endif /* PROCESS_CONF_STATS */  process_current = process_list = NULL;}

process_start(...);
voidprocess_start(struct process *p, process_data_t data){  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, data);}

process_post_synch和process_post的区别我就不介绍了,自己可以对照代码阅读;概念那些我最不擅长,一句话,想学会这个系统,就得不断的去啃代码
下面我们看一下主循环的while中的最重要的函数:
core/sys/process.c中

intprocess_run(void){  /* Process poll events. */  if(poll_requested) {    do_poll();  }  /* Process one event from the queue */  do_event();  return nevents + poll_requested;}

do_poll和do_event的代码自行阅读,但是本质是在处理结构体值后调用了
call_process(...)这个才是正主了

core/sys/process.c中

static voidcall_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", PROCESS_NAME_STRING(p), ev);  }#endif /* DEBUG */    if((p->state & PROCESS_STATE_RUNNING) &&     p->thread != NULL) {    PRINTF("process: calling process '%s' with event %d\n", PROCESS_NAME_STRING(p), 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;    }}


其中的ret = p->thread(&p->pt, ev, data);大家参考test_null.c的PROCESS的写法和我提示的函数指针

是不是应该能知道这个家伙干什么了;


不知不觉都写了这么多字了,算了,下一次再带来编程事件的理解;至少让我先理解Contiki是怎么设计思想

然后再去编写代码;现在已经战战兢兢了,这个系统说是pure c,但是还是不太理解他的所谓的thread,现在就已经接触了不少编程禁忌了,大家知道在最后编写复杂应用如果吃不透他的设计思想一旦代码有BUG,后果是不堪设想的;怀念TinyOS,哪有这么多禁忌!








     
1 0
原创粉丝点击