alert是一个内核对象,允许应用程序在关注的条件发生时执行异步信号传输。
我正在学习 Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总。
可以定义任意数量的 alert。 每个 alert 都由其内存地址引用。
alert 具有以下关键属性:
alert 必须初始化才能使用。 这将建立其警报处理程序并将挂起的计数设置为零。
当检测到无法处理感兴趣的条件时,ISR或线程通过发送 alert 来发出信号。
每次发送 alert 时,内核都会检查 alert 处理程序以确定要采取的操作。
线程通过接收 alert 接受 挂起 alert。这会减少挂起的计数。如果挂起计数为零,则线程将等待 alert 挂起。任何数量的线程可能会同时等待一个挂起的 alert;当 alert 被挂起时,它被等待时间最长的最高优先级线程所接受。
一个线程必须一次处理一个挂起alert。 该线程无法通过单个操作接收多个挂起alert。
Zephyr alert 有点类似于Unix风格的信号,但有很多显着差异。 其中最值得注意的是:
alert 是使用 struct k_alert 类型的变量定义的。 它必须通过调用 k_alert_init() 来初始化。
以下代码定义并初始化一个 alert。 该警报允许多达10个未接收到的 alert 信号挂起,之后就开始忽略新的挂起 alert。
extern int my_alert_handler(struct k_alert *alert);
struct k_alert my_alert;
k_alert_init(&my_alert, my_alert_handler, 10);
或者,可以在编译时通过调用 K_ALERT_DEFINE 来定义和初始化 alert。
以下代码与上面的代码段具有相同的效果。
extern int my_alert_handler(struct k_alert *alert);
K_ALERT_DEFINE(my_alert, my_alert_handler, 10);
alert 通过调用 k_alert_send() 来发送。
以下代码说明了ISR如何发出 alert 来指示按键已经发生。
extern int my_alert_handler(struct k_alert *alert);
K_ALERT_DEFINE(my_alert, my_alert_handler, 10);
void keypress_interrupt_handler(void *arg)
{
...
k_alert_send(&my_alert);
...
}
aert 处理函数用于不应忽视或立即挂起的信号alert。 它有以下形式:
int <function_name>(struct k_alert *alert)
{
/* catch the alert signal; return zero if the signal is consumed, */
/* or non-zero to let the alert pend */
...
}
以下代码说明了一个处理由ISR检测到的按键处理的 alert 处理函数(如前一部分所示)。
int my_alert_handler(struct k_alert *alert_id_is_unused)
{
/* determine what key was pressed */
char c = get_keypress();
/* do complex processing of the keystroke */
...
/* signaled alert has been consumed */
return 0;
}
线程通过调用 k_alert_recv() 来接受挂起 alert。
以下代码是上一节中代码的替代方法。 它使用专用线程来执行非常复杂的按键处理,否则会独占系统工作队列。 alert 处理函数现在仅用于过滤不需要的按键警报,允许专用线程唤醒并仅在按下数字键时处理按键警报。
int my_alert_handler(struct k_alert *alert_id_is_unused)
{
/* determine what key was pressed */
char c = get_keypress();
/* signal thread only if key pressed was a digit */
if ((c >= '0') && (c <= '9')) {
/* save key press information */
...
/* signaled alert should be pended */
return 1;
} else {
/* signaled alert has been consumed */
return 0;
}
}
void keypress_thread(void *unused1, void *unused2, void *unused3)
{
/* consume numeric key presses */
while (1) {
/* wait for a key press alert to pend */
k_alert_recv(&my_alert, K_FOREVER);
/* process saved key press, which must be a digit */
...
}
}
通过将与中断相关的工作推迟到线程来减少中断被锁定的时间,使用 alert 来最小化ISR处理。
使用 alert 来允许内核的系统工作队列处理警报,而不是定义应用程序线程来处理 alert。
在让应用程序线程处理它之前,使用 alert 来允许内核的系统工作队列预处理警报。
无
下列 alert API,都在 kernel.h 中提供了:
K_ALERT_DEFINE
k_alert_init()
k_alert_send()
k_alert_recv()