一文详解Linux内核数据结构之kfifo

本文详细介绍了Linux内核中的FIFO数据结构kfifo,其利用环形队列实现无边界字节流服务,并采用无锁编程确保线程安全。kfifo初始化时保证buffer size为2的幂以优化求余运算,入队、出队操作通过spin_lock_irqsave&spin_unlock_irqrestore保证同步,避免死锁。此外,kfifo结构保持线性,简化判断,利用内存屏障确保内存访问顺序,从而提高效率。
摘要由CSDN通过智能技术生成
本文分析的原代码版本: 2.6.24.4
kfifo的定义文件: kernel/kfifo.c
kfifo的头文件: include/linux/kfifo.h

kfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现,提供一个无边界的字节流服务,并且使用并行无锁编程技术,即当它用于只有一个入队线程和一个出队线程的场情时,两个线程可以并发操作,而不需要任何加锁行为,就可以保证kfifo的线程安全。

下文着重于代码剖析,各部分代码后面有关键点说明,同时可参考注释进行理解:

struct kfifo {
    unsigned char *buffer;    /* the buffer holding the data : 用于存放数据的缓存 */
    unsigned int size;    /* the size of the allocated buffer : 空间的大小,在初化时将它向上扩展成2的幂,为了高效的进行与操作取余,后面会详解 */
    unsigned int in;    /* data is added at offset (in % size) : 如果使用不能保证任何时间最多只有一个读线程和写线程,需要使用该lock实施同步*/
    unsigned int out;    /* data is extracted from off. (out % size) :一起构成一个循环队列。 in指向buffer中队头,而且out指向buffer中的队尾 */
    spinlock_t *lock;    /* protects concurrent modifications : 用于put和get过程中加锁防止并发*/
};

以上是kfifo的数据结构,kfifo主要提供了如下操作:

//根据给定buffer创建一个kfifo
  struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
                  gfp_t gfp_mask, spinlock_t *lock);
  //给定size分配buffer和kfifo
  struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask,
                   spinlock_t *lock);
  //释放kfifo空间
  void kfifo_free(struct kfifo *fifo);
  //向kfifo中添加数据
  unsigned int kfifo_put(struct kfifo *fifo,
                 const unsigned char *buffer, unsigned int len);

  //从kfifo中取数据
  unsigned int kfifo_get(struct kfifo *fifo,
                 unsigned char *buffer, unsigned int len);
 //获取kfifo中有数据的buffer大小 
 unsigned int kfifo_len(struct kfifo *fifo);

(1)初始化部分:

/* 创建队列 */ struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
              gfp_t gfp_mask, spinlock_t *lock)
 {
     struct kfifo *fifo;
     /* size must be a power of 2 :判断是否为2的幂*/
     BUG_ON(!is_power_of_2(size));
     fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
     if (!fifo)
         return ERR_PTR(-ENOMEM);
     fifo->buffer = buffer;
     fifo->size = size;
     fifo->in = fifo->out = 0;
     fifo->lock = lock;
 
     return fifo;
 }
 /* 分配空间 */ struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock)
 {
     unsigned char *buffer;
     struct kfifo *ret;
     if (!is_power_of_2(size)) {  /* 判断是否为2的幂 */
         BUG_ON(size > 0x80000000);
         size = roundup_pow_of_two(size); /* 如果不是则向上扩展成
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值