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


    本文分析的原代码版本: 2.6.24.4
    kfifo的定义文件: kernel/kfifo.c
    kfifo的头文件: include/linux/kfifo.h

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

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

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

    以上是kfifo的数据结构,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_get(struct kfifo *fifo,
    14. unsigned char *buffer, unsigned int len);
    15.  //获取kfifo中有数据的buffer大小
    16.  unsigned int kfifo_len(struct kfifo *fifo);

    (1)初始化部分:

    1. /* 创建队列 */ struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size,
    2. gfp_t gfp_mask, spinlock_t *lock)
    3. {
    4. struct kfifo *fifo;
    5. /* size must be a power of 2 :判断是否为2的幂*/
    6. BUG_ON(!is_power_of_2(size));
    7. fifo = kmalloc(sizeof(struct kfifo), gfp_mask);
    8. if (!fifo)
    9. return ERR_PTR(-ENOMEM);
    10. fifo->buffer = buffer;
    11. fifo->size = size;
    12. fifo->in = fifo->out = 0;
    13. fifo->lock = lock;
    14. return fifo;
    15. }
    16. /* 分配空间 */ struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock)
    17. {
    18. unsigned char *buffer;
    19. struct kfifo *ret;
    20. if (!is_power_of_2(size)) { /* 判断是否为2的幂 */
    21. BUG_ON(size > 0x80000000);
    22. size = roundup_pow_of_two(size); /* 如果不是
  • 相关阅读:
    python二次开发CATIA:新建Part文档
    Java知识点08——多线程
    解决电脑显示找不到msvcp140_CODECVT_IDS.dll文件的办法
    JVM基础08_强软弱虚引用
    关于 ‘cosylocal‘ 进程占满内存的问题
    windows系统安装openssl并且转换证书格式
    使用 Ubuntu + Docker + Vaultwarden + Tailscale 自建密码管理器
    基于图数据库的推荐系统
    android和java 线程Tread
    诸葛广告分析3大能力全面升级,新增巨量引擎渠道广告监测!
  • 原文地址:https://blog.csdn.net/m0_73494896/article/details/126973152