Linux内核kfifo实现详解 Linux内核kfifo是一种高效的无锁环形缓冲区实现,其核心设计包括:1)使用2的幂次方大小缓冲区,通过位运算替代取模运算提高性能;2)分离的in/out索引设计,避免锁机制;3)内存屏障确保数据一致性。kfifo通过位运算优化索引计算(position & mask),并采用两段复制策略处理环形缓冲区的边界条件,在单生产者单消费者场景下实现高效无锁操作。
kfifo设计原理
1.1 核心思想 Linux内核kfifo(kernel FIFO)是一个高效、无锁的环形缓冲区实现,专为内核环境设计。
1 2 3 4 5 6 7 8 9 10 11 12 struct __kfifo { unsigned int in ; unsigned int out ; unsigned int mask; unsigned int esize; void *data; };
1.2 关键设计决策 1.2.1 2的幂次方大小 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 index = position % size; mask = size - 1 ; index = position & mask;
1.2.2 索引分离设计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 struct __kfifo { unsigned int in; unsigned int out; };unsigned int len = fifo->in - fifo->out;unsigned int write_index = fifo->in & fifo->mask;unsigned int read_index = fifo->out & fifo->mask;
内存布局优化
2.1 缓冲区大小计算 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 static int __init kfifo_alloc_common(struct __kfifo *fifo, unsigned int size, size_t esize, gfp_t gfp_mask) { size = roundup_pow_of_two(size); fifo ->in = 0 ; fifo -> out = 0 ; fifo -> esize = esize; if (size < 2 ) { fifo ->data = NULL; fifo -> mask = 0 ; return -EINVAL; } fifo ->data = kmalloc(size * esize, gfp_mask); if (!fifo->data ) { fifo -> mask = 0 ; return -ENOMEM; } fifo -> mask = size - 1 ; return 0 ; }
2.2 位运算优化详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 /** * 位运算优化示例 */ // 传统方法:使用取模运算 int traditional_index(int position, int size) { return position % size; // 涉及除法运算,较慢 } // kfifo方法:使用位运算 int optimized_index(int position, int mask) { return position & mask; // 位运算,非常快 } // 示例对比: // size = 8 (2^3), mask = 7 (0111) // position = 0..15 的索引计算: // 位置 0: 0 & 7 = 0 0 % 8 = 0 // 位置 1: 1 & 7 = 1 1 % 8 = 1 // 位置 7: 7 & 7 = 7 7 % 8 = 7 // 位置 8: 8 & 7 = 0 8 % 8 = 0 (循环回到开始) // 位置 9: 9 & 7 = 1 9 % 8 = 1 (循环)
无锁设计原理
3.1 单生产者单消费者无锁实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 unsigned int kfifo_in(struct __kfifo *fifo, const void *buf, unsigned int len) { unsigned int l; len = min(len, fifo->mask + 1 - fifo->in + fifo-> out); l = min(len, fifo->mask + 1 - (fifo->in & fifo-> mask)); memcpy (fifo->data + (fifo->in & fifo->mask ) * fifo->esize , buf, l * fifo-> esize); memcpy (fifo->data , (char *)buf + l * fifo-> esize, (len - l) * fifo-> esize); smp_wmb(); fifo ->in += len; return len; } unsigned int kfifo_out(struct __kfifo *fifo, void *buf, unsigned int len) { unsigned int l; len = min(len, fifo->in - fifo-> out); l = min(len, fifo->mask + 1 - (fifo->out & fifo-> mask)); memcpy (buf, fifo->data + (fifo->out & fifo->mask ) * fifo->esize , l * fifo-> esize); memcpy ((char *)buf + l * fifo->esize , fifo->data , (len - l) * fifo-> esize); smp_mb(); fifo -> out += len; return len; }
3.2 内存屏障的作用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 smp_wmb(); fifo ->in += len; smp_mb(); fifo -> out += len;
边界条件处理
4.1 环形缓冲区的两段复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 unsigned int kfifo_in(struct __kfifo *fifo, const void *buf, unsigned int len) { unsigned int l; l = min(len, fifo->mask + 1 - (fifo->in & fifo-> mask)); memcpy (fifo->data + (fifo->in & fifo->mask ) * fifo-> esize, buf, l * fifo-> esize); memcpy (fifo->data , (char *)buf + l * fifo-> esize, (len - l) * fifo-> esize); fifo ->in += len; return len; }
4.2 空/满状态判断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #define kfifo_is_empty(fifo) \ ({ \ typeof((fifo) + 1 ) __tmp = (fifo); \ struct __kfifo *__kfifo = &__tmp-> kfifo; \ __kfifo ->in == __kfifo-> out; \ }) #define kfifo_is_full(fifo) \ ({ \ typeof((fifo) + 1 ) __tmp = (fifo); \ struct __kfifo *__kfifo = &__tmp-> kfifo; \ kfifo_len (__tmp) == __kfifo-> mask + 1 ; \ }) #define kfifo_len(fifo) \ ({ \ typeof((fifo) + 1 ) __tmp = (fifo); \ struct __kfifo *__kfifo = &__tmp-> kfifo; \ __kfifo ->in - __kfifo-> out; \ })
类型安全的宏设计
5.1 泛型支持 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #define DECLARE_KFIFO(name, size) \ struct { \ struct __kfifo kfifo; \ typeof (name) *rectype; \ } name#define kfifo_put(fifo, val) \ ({ \ typeof ((fifo) + 1 ) __tmp = (fifo); \ typeof (*val) __val = (val); \ unsigned int __ret; \ size_t __recsize = sizeof (*__tmp->rectype); \ struct __kfifo *__kfifo = &__tmp->kfifo; \ __ret = __kfifo_uint32s_put(__kfifo, __val, __recsize); \ __ret; \ })#define kfifo_get(fifo, val) \ ({ \ typeof ((fifo) + 1 ) __tmp = (fifo); \ typeof (val) __val = (val); \ unsigned int __ret; \ const size_t __recsize = sizeof (*__tmp->rectype); \ struct __kfifo *__kfifo = &__tmp->kfifo; \ __ret = __kfifo_uint32s_out(__kfifo, __val, __recsize); \ __ret; \ }) DECLARE_KFIFO(my_fifo, 32 ); int value = 42 ; kfifo_put(&my_fifo, &value ); kfifo_get(&my_fifo, &value );
5.2 编译时检查 1 2 3 4 5 6 7 8 9 10 11 /** * 编译时类型检查 */#define __KFIFO_PEEK(data, out, mask) \ ((data )[(out ) & (mask )])#define __KFIFO_POKE(data, in, mask, val) \ ( (data )[(in ) & (mask )] = (val ) ) // 这些宏确保在编译时就能发现类型错误
性能优化技术
6.1 缓存友好性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 struct __kfifo { unsigned int in ; unsigned int out ; unsigned int mask; unsigned int esize; void *data; };
6.2 编译器优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 static inline unsigned int kfifo_len (struct __kfifo *fifo) { return fifo->in - fifo->out; }#define KFIFO_SIZE 1024 #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0)
实际应用场景
7.1 内核中的典型应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 struct sk_buff_head { struct __kfifo skb_queue; };struct workqueue_struct { struct __kfifo work_list; };struct tty_port { struct __kfifo buf; };struct irq_desc { struct __kfifo pending_mask; };
7.2 用户空间移植 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
设计优势总结
8.1 性能优势 O(1)时间复杂度:所有操作都是常数时间
位运算优化:避免除法运算
缓存友好:数据局部性好
无锁设计:单生产者单消费者场景下无需锁
8.2 内存优势 紧凑布局:控制信息集中存储
零拷贝支持:直接内存访问
动态分配:按需分配内存
8.3 使用优势 类型安全:编译时类型检查
接口简洁:易于使用
广泛测试:内核级稳定性保证
8.4 可扩展性 泛型支持:支持任意数据类型
可配置大小:动态调整缓冲区大小
多线程支持:提供同步版本
这个设计体现了Linux内核对性能、可靠性和简洁性的极致追求,是系统编程的经典范例。
Linux内核kfifo实现详解-CSDN博客
https://www.calcguide.tech/2025/08/24/linux内核kfifo实现详解/
https://www.calcguide.tech/2025/08/23/getitimer系统调用及示例/
相关阅读