LIFO
LIFO 是实现传统后进先出(LIFO)队列的内核对象,允许线程和 ISR 添加或移除任意大小的数据项。
概念
可以定义任意数量的 LIFO(仅受可用 RAM 限制)。每个 LIFO 都通过其内存地址引用。
LIFO 具有以下主要属性:
一个 队列,存放已添加但尚未移除的数据项。队列通过简单的链表实现。
LIFO 必须初始化后才能使用。初始化会将其队列置空。
LIFO 数据项必须满足指针的对齐要求,因为内核会保留数据项开头一个指针大小的字段,用于指向队列中的下一个数据项。因此,容纳 N 字节应用数据的数据项需要 N+4(或 N+8)字节内存。如果使用 k_lifo_alloc_put() 添加数据项,则无需满足上述对齐和预留空间要求,而是从调用线程的资源池中临时分配额外内存。
备注
同一个 LIFO 数据项在所有 LIFO 数据队列中最多只能有一个在用实例。在数据项尚未从此前加入的队列中移除时,尝试将它再次加入队列会导致未定义行为。
线程或 ISR 均可向 LIFO 添加 数据项。如果有线程正在等待,则直接将数据项交给该线程;否则将其加入 LIFO 队列。队列中的数据项数量没有上限。
线程可以从 LIFO 移除 数据项。如果 LIFO 队列为空,线程可以选择等待数据项到来。任意数量的线程都可以同时等待一个空 LIFO。添加数据项后,它会被交给优先级最高且等待时间最长的线程。
备注
内核允许 ISR 从 LIFO 移除数据项,但 LIFO 为空时,ISR 不得尝试等待。
实现
定义 LIFO
LIFO 使用 k_lifo 类型的变量定义,随后必须调用 k_lifo_init() 进行初始化。
以下代码定义并初始化一个空 LIFO。
struct k_lifo my_lifo;
k_lifo_init(&my_lifo);
也可以使用 K_LIFO_DEFINE 在编译时定义并初始化一个空 LIFO。
以下代码与上面的代码片段效果相同。
K_LIFO_DEFINE(my_lifo);
写入 LIFO
调用 k_lifo_put() 可以向 LIFO 添加数据项。
以下代码延续上面的示例,使用 LIFO 向一个或多个消费者线程发送数据。
struct data_item_t {
void *LIFO_reserved; /* 1st word reserved for use by LIFO */
...
};
struct data_item_t tx data;
void producer_thread(int unused1, int unused2, int unused3)
{
while (1) {
/* create data item to send */
tx_data = ...
/* send data to consumers */
k_lifo_put(&my_lifo, &tx_data);
...
}
}
可以使用 k_lifo_alloc_put() 向 LIFO 添加数据项。使用此 API 时,无需在数据项中为内核预留空间;它会从调用线程的资源池中分配额外内存,直到数据项被读取后才释放。
读取 LIFO
调用 k_lifo_get() 可以从 LIFO 移除数据项。
以下代码延续上面的示例,使用 LIFO 从生产者线程获取数据项,然后对其进行处理。
void consumer_thread(int unused1, int unused2, int unused3)
{
struct data_item_t *rx_data;
while (1) {
rx_data = k_lifo_get(&my_lifo, K_FOREVER);
/* process LIFO data item */
...
}
}
使用建议
使用 LIFO 以“后进先出”的方式异步传递任意大小的数据项。
配置选项
相关配置选项:
无。