内核中的队列是以字节形式保存数据的,所以获取数据的时候,需要知道数据的大小。
如果从队列中取得数据时指定的大小不对的话,取得数据会不完整或过大。
内核中关于队列定义的头文件位于:<linux/kfifo.h> include/linux/kfifo.h
头文件中定义的函数的实现位于:kernel/kfifo.c
内核队列编程需要注意的是:
- 队列的size在初始化时,始终设定为2的n次方
- 使用队列之前将队列结构体中的锁(spinlock)释放
1. kfifo概述
kfifo 是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现;它提供一个无边界的字节流服务,最重要的一点是,它使用并行无锁编程技术,即当它用于只有一个入队线程和一个出队线程的场情时,两个线程可以并发操作,而不需要任何加锁行为,就可以保证kfifo的线程安全。
struct kfifo {
unsignedchar *buffer; /* the buffer holdingthe data */
unsignedint size; /* the size of the allocatedbuffer */
unsignedint in; /* data is added at offset (in% size) */
unsignedint out; /* data is extracted fromoff. (out % size) */
spinlock_t*lock; /* protects concurrentmodifications */
};
这是kfifo的数据结构,kfifo主要提供了两个操作,__kfifo_put(入队操作)和__kfifo_get(出队操作)。 它的各个数据成员如下:
buffer, 用于存放数据的缓存
size, buffer空间的大小,在初化时,将它向上扩展成2的幂
lock, 如果使用不能保证任何时间最多只有一个读线程和写线程,需要使用该lock实施同步。
in, out, 和buffer一起构成一个循环队列。 in指向buffer中队尾,而且out指向buffer中的队头,in是数据被开始存放的偏移位置,out是队列开始取出数据的偏移位置。它的结构如示图如下:
+--------------------------------------------------------------+
| |<----------data---------->| |
+--------------------------------------------------------------+
^ ^
| |
out in
在put和get函数中堆in,out做了很巧妙的处理!
2. kfifo_alloc 分配kfifo内存和初始化工作
struct kfifo*kfifo_alloc(unsigned int size, gfp_t gfp_m