Fifo¶
fifo 是一个内核对象,它实现了传统的先进先出(first in first out)队列,允许线程 和 ISR 添加、移除任意尺寸的数据项。
概念¶
可以定义任意数量的 fifo。每个 fifo 通过其内存地址进行引用。
fifo 的关键属性包括:
- 队列:它里面包含了已被添加但还未被移除的数据项。队列是使用一个简单的单链表实现的。
fifo 必须初始化加再使用。初始化时会将队列设为空。
fifo 的数据项必须在 4 字节边界上对齐,这是因为每个数据项的前 32 比特是内核保留的,它(被当做指针)用来指向队列中的下一个数据项。因此,如果应用程序需要 N 字节的数据项时,实际需要 N+4 字节的内存。
数据项可以被线程或者 ISR 添加 到 fifo 中。如果有线程在等待从这个 fifo 中取数据,这个数据项则直接被给予这个线程;否则,该项会被直接添加到 fifo 的队列中去。对可入队的数据项的数量没有任何限制。
数据项可以被线程从 fifo 中 移除。如果该 fifo 的队列为空,线程在这个 fifo 上进行等待。多个线程可以同时在某个空 fifo 上等待,当一个新的数据项被添加时,它会被给予优先级最高的、等待时间最久的线程。
注解
ISR 虽然也可以从 fifo 中移除数据,但是如果 fifo 为空,ISR 不能进行等待。
如果有需要,链接为单链表的 多个数据项 可以一次性添加到 fifo 中。当多个写者正在添加一系列相关的数据项(集合)到 fifo 中时,能体现处这种做法的好处,因为这能确保每个被添加到 fifo 中的同一个集合中的数据项不能被其它集合的数据项交错开。一个性添加多个数据项比每次添加一个数据项的效率更高,且能保证移除集合中第一个数据项的线程或者 ISR 不需要等待就能移除该集合中剩余的数据项。
实现¶
定义 fifo¶
使用类型为 struct k_fifo
的变量可以定义一个 fifo。fifo 定义后必须使用函数 k_fifo_init()
进行初始化。
下面的代码定义并初始化了一个空 fifo。
struct k_fifo my_fifo;
k_fifo_init(&my_fifo);
也可以使用宏 K_FIFO_DEFINE
在编译时定义并初始化一个 fifo。
下面的代码与上面的代码段具有相同的效果。
K_FIFO_DEFINE(my_fifo);
向 fifo 中写¶
函数 k_fifo_put()
可用于向 fifo 中写数据。
下面的代码基于上面的例程之上,它使用 fifo 给一个或多个消费者线程发送数据。
struct data_item_t {
void *fifo_reserved; /* 1st word reserved for use by fifo */
...
};
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_fifo_put(&my_fifo, &tx_data);
...
}
}
函数 k_fifo_put_list()
或者 k_fifo_put_slist()
可用于将一个单链表数据项添加到 fifo 中。