FIFO 与 LIFO
本页依据 文档基线与后续更新 中记录的 Zephyr main 快照更新。
FIFO 按进入顺序取出对象,LIFO 优先取出最后加入的对象。二者都传递对象地址, 不会自动复制应用载荷。等待者的调度优先级与队列中数据的顺序是两个独立概念。
定义与内存布局
普通 k_fifo_put()、k_lifo_put() 要求数据按本机字对齐,并保留首个字供内核链接。
可在结构体首部放置 void *:
#include <zephyr/kernel.h>
#include <errno.h>
struct sample {
void *fifo_reserved;
uint32_t value;
};
K_FIFO_DEFINE(samples);
K_MEM_SLAB_DEFINE(sample_pool, sizeof(struct sample), 8, sizeof(void *));
int enqueue_sample(uint32_t value)
{
struct sample *item;
int rc = k_mem_slab_alloc(&sample_pool, (void **)&item, K_NO_WAIT);
if (rc != 0) {
return rc;
}
item->value = value;
k_fifo_put(&samples, item);
return 0; /* 所有权交给消费者 */
}
int dequeue_sample(uint32_t *value)
{
struct sample *item = k_fifo_get(&samples, K_MSEC(100));
if (item == NULL) {
return -EAGAIN;
}
*value = item->value;
k_mem_slab_free(&sample_pool, item);
return 0;
}
同一对象同时只能处于一个队列中,取出前不得重复 put。 示例用 slab 管理生命周期,避免把生产者的临时栈变量排队后立即失效。
动态包装与批量插入
k_fifo_alloc_put()、k_lifo_alloc_put() 为链接信息申请额外包装存储,
因此数据对象不必自行预留首字。此分配使用调用线程的资源池,可能失败;
它仍然没有复制或取得应用载荷的永久所有权。
FIFO 支持 k_fifo_put_list() 和 k_fifo_put_slist() 批量加入链表。
链表的组织方式必须符合对应接口要求。LIFO 使用
K_LIFO_DEFINE、k_lifo_put()、k_lifo_get(),取出顺序相反。
读取与等待
get 成功返回对象指针,无数据、超时或取消等待时返回 NULL,应在解引用前检查。
线程可等待,ISR 只能使用 K_NO_WAIT。存在等待者时,新数据可直接交给等待线程。
FIFO 可配合 轮询多个内核对象 等待,但 poll 不预留数据,之后的 get 仍可能返回 NULL。
不要依赖 k_queue 内部节点标记或链表字段的历史实现来编写应用。