linux内核之Kfifo环形队列

本文介绍了Linux内核中的Kfifo环形队列,它常用于实现环形缓冲区,以解决生产者和消费者模型中的数据同步问题。文章详细探讨了Kfifo的数据结构、初始化、入队和出队操作,并提供了测试程序来演示其工作原理。通过并发控制的ring_buffer示例,展示了如何在实际应用中使用Kfifo。
摘要由CSDN通过智能技术生成

1、前言

  最近项目中用到一个环形缓冲区(ring buffer),代码是由linux内核的kfifo改过来的。缓冲区在文件系统中经常用到,通过缓冲区缓解cpu读写内存和读写磁盘的速度。例如一个进程A产生数据发给另外一个进程B,进程B需要对进程A传的数据进行处理并写入文件,如果B没有处理完,则A要延迟发送。为了保证进程A减少等待时间,可以在A和B之间采用一个缓冲区,A每次将数据存放在缓冲区中,B每次冲缓冲区中取。这是典型的生产者和消费者模型,缓冲区中数据满足FIFO特性,因此可以采用队列进行实现。Linux内核的kfifo正好是一个环形队列,可以用来当作环形缓冲区。生产者与消费者使用缓冲区如下图所示:

  环形缓冲区的详细介绍及实现方法可以参考http://en.wikipedia.org/wiki/Circular_buffer,介绍的非常详细,列举了实现环形队列的几种方法。环形队列的不便之处在于如何判断队列是空还是满。维基百科上给三种实现方法。

2、linux 内核kfifo

  kfifo设计的非常巧妙,代码很精简,对于入队和出对处理的出人意料。首先看一下kfifo的数据结构:

复制代码
struct kfifo {
    unsigned char *buffer;     /* the buffer holding the data */
    unsigned int size;         /* the size of the allocated buffer */
    unsigned int in;           /* data is added at offset (in % size) */
    unsigned int out;          /* data is extracted from off. (out % size) */
    spinlock_t *lock;          /* protects concurrent modifications */
};
复制代码

kfifo提供的方法有:

复制代码
 1 //根据给定buffer创建一个kfifo
 2 struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
 3                 gfp_t gfp_mask, spinlock_t *lock);
 4 //给定size分配buffer和kfifo
 5 struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask,
 6                  spinlock_t *lock);
 7 //释放kfifo空间
 8 void kfifo_free(struct kfifo *fifo)
 9 //向kfifo中添加数据
10 unsigned int kfifo_put(struct kfifo *fifo,
11                 const unsigned char *buffer, unsigned int len)
12 //从kfifo中取数据
13 unsigned int kfifo_put(struct kfifo *fifo,
14                 const unsigned char *buffer, unsigned int len)
15 //获取kfifo中有数据的buffer大小
16 unsigned int kfifo_len(struct kfifo *fifo)
复制代码

       定义自旋锁的目的为了防止多进程/线程并发使用kfifo。因为in和out在每次get和out时,发生改变。初始化和创建kfifo的源代码如下:

复制代码
 1 struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
 2              gfp_t gfp_mask, spinlock_t *lock)
 3 {
 4     struct kfifo *fifo;
 6     /* size must be a power of 2 */
 7     BUG_ON(!is_power_of_2(size));
 9     fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
10     if (!fifo)
11         return ERR_PTR(-ENOMEM);
13     fifo->buffer = buffer;
14     fifo->size = size;
15     fifo->in = fifo->out = 0;
16     fifo->lock = lock;
17 
18     return fifo;
19 }
20 struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock)
21 {
22     unsigned char *buffer;
23     struct kfifo *ret;
29     if (!is_power_of_2(size)) {
30         BUG_ON(size > 0x80000000);
31         size = roundup_pow_of_two(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值