kfifo使用了in和out两个变量分别作为入队和出队的索引: 入队n个数据时,in变量就+n 出队k个数据时,out变量就+k out不允许大于in(out等于in时表示fifo为空) in不允许比out大超过fifo空间(比如上图,in最多比out多8,此时表示fifo已满) 如果in和out大于fifo空间了,比如上图中的8,会减去8后重新开始吗? 不,...
fifo->size - fifo->in+ fifo->out);78/*9* Ensure that we sample the fifo->out index -before- we10* start putting bytes into the kfifo.11*/1213smp_mb();1415/*first put the data starting from fifo->in to buffer end*/16l = min(len, fifo->size...
再看下kfifo内存分配和初始化的代码,前面提到kfifo总是对size进行2次幂的圆整,这样的好处不言而喻,可以将kfifo->size取模运算可以转化为与运算,如下: kfifo->in % kfifo->size 可以转化为 kfifo->in & (kfifo->size – 1) “取模运算”的效率并没有 “位运算” 的效率高还记得不,不放过任何一点可以提高...
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 */ }; 1 2 3 4 5 6 7 这是kfifo的数据结构,kfifo主要提供了两个操作,__kfifo_put(入队操作)和__...
kfifo是内核里面的一个First In First Out数据结构,它采用环形循环队列的数据结构来实现;它提供一个无边界的字节流服务,最重要的一点是,它使用并行无锁编程技术,即当它用于只有一个入队线程和一个出队线程的场情时,两个线程可以并发操作,而不需要任何加锁行为,就可以保证kfifo的线程安全。
__kfifo_put是入队操作,它先将数据放入buffer里面,最后才修改in参数;__kfifo_get是出队操作,它先将数据从buffer中移走,最后才修改out。你会发现in和out两者各司其职。计算机科学家已经证明,当只有一个读经程和一个写线程并发操作时,不需要任何额外的锁,就可以确保是线程安全的,也即kfifo使用了无锁编程技术,以提...
再看下kfifo内存分配和初始化的代码,前面提到kfifo总是对size进行2次幂的圆整,这样的好处不言而喻,可以将kfifo->size取模运算可以转化为与运算,如下: kfifo->in % kfifo->size 可以转化为 kfifo->in & (kfifo->size – 1) “取模运算”的效率并没有 “位运算” 的效率高还记得不,不放过任何一点可以提高...
Linux内核的Kfifo正是为此设计的高效环形队列。其数据结构精简,入队和出队操作巧妙。关键在于使用无符号类型表示的in和out指针,它们在每次操作时递增,当达到最大值时自动循环回零,实现循环使用。为避免多进程/线程并发访问导致的冲突,Kfifo采用自旋锁机制。初始化时,Kfifo会将传入的size参数扩展至2的幂...
在kfifo_init和kfifo_calloc中,kfifo->size的值总是在调用者传进来的size参数的基础上向2的幂扩展,这是内核一贯的做法。这样的好处不言而喻--对kfifo->size取模运算可以转化为与运算,如:kfifo->in % kfifo->size 可以转化为 kfifo->in & (kfifo->size – 1) kfifo的巧妙之处在于in和out定义为无符号类型...
所以fifo->size - (fifo->in & (fifo->size - 1)) 即位 fifo->in 到 buffer末尾所剩余的长度,l取len和剩余长度的最小值,即为需要拷贝l 字节到fifo->buffer + fifo->in的位置上。