contiki-ng文档:进程和事件

Contiki-NG中的应用程序通常是使用Process抽象编写的。 进程建立在称为Protothreads的轻量级线程库的顶部。

进程定义

首先在源文件的顶部声明一个进程。 PROCESS()宏带有两个参数:一个是用于标识进程的变量,另一个是进程的名称。 在第二行中,我们告诉Contiki-NG,该过程应在系统启动后立即自动启动。 可以在此处指定多个进程,以逗号分隔。 如果AUTOSTART_PROCESSES()行不包含现有进程,则必须使用process_start()函数手动启动该进程。

#include "contiki.h" /* Main include file for OS-specific modules. */
#include <stdio.h> /* For printf. */

PROCESS(test_proc, "Test process");
AUTOSTART_PROCESSES(&test_proc);

下面是一个基本的的进程定义

PROCESS_THREAD(test_proc, ev, data)
{
  PROCESS_BEGIN();

  printf("Hello, world!\n");

  PROCESS_END();
}

首先,PROCESS_THREAD()宏采用PROCESS()调用中指定的进程的标识符。 evdata参数包含传入事件的值,以及指向事件参数对象的可选指针。 PROCESS_BEGIN()标记将开始执行过程的位置。 在大多数情况下,除变量定义外,程序员应避免将代码放在PROCESS_THREAD()主体中此语句上方。

对于我们的基本流程实现,我们不必关心任何事件处理,因为我们只执行一条语句,然后通过让其到达PROCESS_END()调用隐式退出流程。

事件和调度

Contiki-NG建立在基于事件的执行模型上,在该模型中,进程通常在告诉调度程序它们正在等待事件之前执行大量工作,从而暂停执行。 此类事件可能是计时器到期、传入的网络数据包或正在传递的串口消息。

contiki采用协同式进程调度,这意味着每个进程负责将控制权自愿交还给操作系统,而不去执行太长时间。 因此,应用程序开发人员必须确保将长时间运行的操作拆分为多个进程调度,以允许调度程序在上一次停止的位置恢复。

等待事件

通过在PROCESS_BEGIN()PROCESS_END()之间区域中调用PROCESS_WAIT_EVENT_UNTIL(),可以将控制权交给调度程序,并且仅在事件到达时才恢复执行。 给出了一个条件作为PROCESS_WAIT_EVENT_UNTIL()的参数,必须满足此条件才能使进程在调用PROCESS_WAIT_EVENT_UNTIL()之后继续执行。 如果不满足该条件,则该过程将控制权交还给OS,直到传递新事件为止。

PROCESS_THREAD(test, ev, data)
{
  /* An event-timer variable. Note that this variable must be static
     in order to preserve the value across yielding. */
  static struct etimer et;

  PROCESS_BEGIN();

  etimer_set(&et, CLOCK_SECOND); /* Trigger a timer after 1 second. */
  while(1) {
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
    etimer_reset(&et);
  }

  PROCESS_END();
}

暂停和退让

要自愿释放对调度程序的控制,可以调用PROCESS_PAUSE(),如下例所示。 然后,调度程序将传递所有排队的事件,然后立即调度已暂停的进程。

PROCESS_THREAD(test_proc, ev, data)
{
  PROCESS_BEGIN();

  while(have_operations_to_do()) {
    do_some_operations();
    PROCESS_PAUSE();
  }

  PROCESS_END();
}

相比之下,PROCESS_YIELD()会将控制权交还给调度程序,而不希望此后不久再进行调度。 相反,它将等待传入事件,类似于PROCESS_WAIT_EVENT_UNTIL(),但没有必需的条件参数。 可以通过调用process_poll()由外部进程或模块轮询已产生的进程。 要轮询使用变量test_proc声明的进程,可以调用process_poll(&test_proc);。 轮询进程将立即进行调度,并且将向其发送PROCESS_EVENT_POLL事件。

停止进程

一个过程可以通过三种方式停止:

  • 通过允许到达并执行PROCESS_END()语句,该过程隐式退出。
  • 通过在PROCESS_THREAD主体中调用PROCESS_EXIT(),显式退出该进程。
  • 另一个进程通过调用process_exit()终止该进程。
    停止进程后,可以通过调用process_start()从头开始重新启动。

系统定义的事件

Contiki-NG使用基于系统定义的事件进行常见操作,如下所示。

Event ID Description
PROCESS_EVENT_NONE 0x80 无事件
PROCESS_EVENT_INIT 0x81 传递给正在开始的进程
PROCESS_EVENT_POLL 0x82 传递给正在轮询的进程.
PROCESS_EVENT_EXIT 0x83 传递给正在退出的进程。
PROCESS_EVENT_SERVICE_REMOVED 0x84 未使用的.
PROCESS_EVENT_CONTINUE 0x85 交付给从暂停中恢复执行时的进程。
PROCESS_EVENT_MSG 0x86 在发生传感器事件时传递给进程。
PROCESS_EVENT_EXITED 0x87 Delivered to all processes about an exited process.
PROCESS_EVENT_TIMER 0x88 当某个计时器到期时,将其交付给进程。
PROCESS_EVENT_COM 0x89 Unused.
PROCESS_EVENT_MAX 0x8a 系统定义的事件的最大数量。

用户自定义的事件

还可以指定系统定义的事件未涵盖的新事件。 应该在适当的范围内定义和声明事件变量,以便该事件的所有预期用户都可以访问它。 基本情况是仅在单个模块中使用它,然后可以在模块顶部将其定义为静态。

static process_event_t my_app_event;
[...]
my_app_event = process_alloc_event();

请注意,不支持取消事件的方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容