2016-11-19 57 views
0

我从书上读到的事件驱动编程:执行上下文驱动的编程

Practical UML Statecharts in C/C++, 2nd Edition: Event-Driven Programming for Embedded Systems

在页面没有。二十八介绍,作者说:

...事件驱动的应用程序必须处理 每次活动后返回控制,所以执行上下文不能在 基于堆栈的变量和程序计数器,因为它被保留在顺序 程序中。相反,事件驱动的应用程序变成了一个状态机器,或者实际上是一组协作状态机,它们将变量中的一个事件保持在下一个事件中的下一个状态机器。

我无法理解为什么在处理事件后返回控件后,无法在基于堆栈的变量和程序计数器中保留执行上下文?

回答

1

让我们从传统的顺序编程范例的工作开始。假设你想让嵌入式主板上的LED闪烁。一个常见的解决方案是将写一个程序是这样的(例如,参见Arduino Blink tutorial):

while (1) { /* RTOS task or a "superloop" */ 
    turn_LED_on(); /* turn the LED on (computation) */ 
    delay(500);  /* wait for 500 ms (polling or blocking) */ 
    turn_LED_off(); /* turn the LED off (computation) */ 
    delay(1000); /* wait for 1000 ms (polling or blocking) */ 
} 

这里的关键点是delay()函数,它等待在线直到延迟为止。这个等待被称为“阻塞”,因为呼叫程序被阻止,直到delay()返回。

请注意的Blinky程序调用两个delay()不同的上下文:turn_LED_on()之后的第一时间和turn_LED_off()后的第二次。每次,delay()都返回到代码中的不同位置。这意味着,当程序被阻止时,代码中的地点信息(呼叫的上下文)会自动保存。

Blinky程序非常简单,但原则上阻塞函数,如delay(),可以从其他函数调用,每个函数都有 复杂的if-else-while代码。但是,delay()将能够返回到调用的确切点,因为C编程语言保留了调用的上下文(在调用堆栈和程序计数器中)。

但阻止使整个程序对任何其他事件没有响应,因此人们想出了event-driven programming

事件驱动程序围绕event-loop构建。一个例子事件驱动的代码看起来是这样的:

while (1) { /* event-loop */ 
    Event *e = queue_get(); /* block when event queue is empty */ 
    dispatch(e); /* handle the event, cannot block! */ 
} 

主要的一点是,dispatch()“事件处理程序”功能不能呼叫阻塞函数像delay()。相反,dispatch()只能执行一些即时操作,并且必须快速返回到事件循环。这样,事件循环始终保持响应

但是,通过返回dispatch()函数从调用堆栈中删除自己的堆栈帧。所以与调用dispatch()相关联的调用堆栈和程序计数器总是相同的,并且无法“记住”执行上下文。

相反,要使LED闪烁,dispatch()功能必须依赖一些记忆LED状态(开/关)的变量(state)。你怎么能写这样dispatch()功能的示例如下:

static enum {OFF, ON } state = OFF; /* start in the OFF state */ 
timer_arm(1000); /* arm a timer to generate TIMEOUT event in 1000 ms */ 

void dispatch(Event *e) { 
    switch (state) { 
     case OFF: 
      if (e->sig == TIMEOUT) { 
       turn_LED_on(); 
       timer_arm(500); 
       state = ON; /* transition to "ON" state */ 
      } 
     break; 
     case ON: 
      if (e->sig == TIMEOUT) { 
       turn_LED_off(); 
       timer_arm(1000); 
       state = OFF; /* transition to "OFF" state */ 
      } 
     break; 
    } 
} 

我希望你能看到dispatch()实现与ON和OFF由一个事件驱动TIMEOUT状态的state machine

相关问题