linux内核无锁缓冲队列kfifo原理
Linux kernel里面从来就不缺少简洁,优雅和高效的代码 比如,通过限定写入的数据不能溢出和内存屏障实现在单线程写单线程读的情况下不使用锁。因为锁是使用在共享资源可能存在冲突的情况下。还用设置buffer缓冲区的大小为2的幂次方,以简化求模运算,这样求模运算就演变为?(fifo->in & (fifo->size - 1))。通过使用unsigned int为kfifo的下标,可以不用考虑每次下标超过size时对下表进行取模运算赋值,这里使用到了无符号整数的溢出回零的特性。由于指示读写指针的下标一直在增加,没有进行取模运算,知道其溢出,在这种情况下写满和读完就是不一样的标志,写满是两者指针之差为fifo->size,读完的标志是两者指针相等。后面有一篇博客还介绍了VxWorks下的环形缓冲区的实现机制点击打开链接,从而可以看出linux下的fifo的灵巧性和高效性。
本文主要以下三个部分:
关于内存屏障的本文不作过多分析,可以参考WikiMemory Barrier。另外,本文所涉及的整数都默认为无符号整数,不再做一一说明。 1. 2的次幂
/* 判断n是否是2的幂 若n为2的次幂,则 n & (n-1) == 0,也就是n和n-1的各个位都不相同。例如 8(1000)和7(0111) 若n不是2的次幂,则 n & (n-1) != 0,也就是n和n-1的各个位肯定有相同的,例如7(0111)和6(0110) */ static inline bool is_power_of_2(uint32_t n) { return (n != 0 && ((n & (n - 1)) == 0)); }
讲解最详细的一篇https://blog.csdn.net/linyt/article/details/53355355另外一个https://www.cnblogs.com/wangguchangqing/p/6070286.htmlstatic inline uint32_t roundup_power_of_2(uint32_t a) { if (a == 0) return 0; uint32_t position = 0; for (int i = a; i != 0; i >>= 1) position++; return static_cast<uint32_t>(1 << position); }
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |