在操作系统内核中,一个常见的编程模式就是生产者和消费者。实现这种模式的最容易的方式就是队列。生产者将数据插入队列,消费者将数据移出队列。消费者以数据进队的顺序消费数据。
内核中通用队列的实现称为kfifo,其实现文件位于kernel/kfifo.c中。提供两个主要的操作:enqueue()和dequeue()。kfifo对象维护了两个偏移量:入口偏移量和出口偏移量。入口偏移量是下次进队发生的位置,出口偏移量是出队发生的位置。出口偏移量问题小于或等于入口偏移量。enqueue操作从入口偏移量处开始,将数据拷贝到队列中,操作完成后,入口偏移量相应的增加(拷进的数据长度)。dequeue操作从出口偏移量处开始,将数据拷贝出队列,操作完成后,出口偏移量相应地增加(拷出的数据长度)。
kfifo对象维护两个偏移量:入口偏移和出口偏移。入口偏移就是下次入队列时的位置,出口偏移就是下一次出队列时的位置。出口偏移总是小于等于入口偏移,否则无意义。
1. 创建队列
动态创建和初始化kfifo:
该函数创建并且初始化一个大小为size的kfifo,同时为之分配了内存(kmalloc函数)。
值得注意的是,size必须是2的幂,若传入的size不是2的幂,函数就会向上扩展至2的幂。
若先前分配了内存空间buffer,将其初始化为kfifo:
2. 推入数据队列
该函数把from指针所指的len字节的数据拷贝到fifo所指队列中。若成功,返回推入数据的字节大小;如果队列中空闲字节小于len,则拷贝剩余空间的字节数;若返回值为0,说明队列已满。
3. 摘取队列数据
该函数从fifo队列中拷贝长度为len字节的数据到to指向的缓冲区,成功则返回拷贝的数据长度,若队列中数据大小小于len则返回实际读取的数据长度。
4. 获取kfifo队列中已推入数据的大小:
5. 判断队列是否为空:
6. 判断队列是否满: