kfifo 的一些伪代码

 kfifo_len()
out = LOAD fifo->out
smp_rmb()
len = LOAD fifo->in - out kfifo_in() kfifo_out()
kfifo_len() kfifo_len() smp_mb() smp_rmb() off = LOAD fifo->in + off off = LOAD fifo->out + off /* memcpy */ /* memcpy */ smp_wmb() smp_mb() STORE fifo->in += off STORE fifo->out += off

kfifo_in 只修改 fifo->in 的值,含一个 STORE 指令,及若干 fifo->out fifo->in 的 LOAD 指令
kfifo_out 相反,只修改 kfifo->out 的值,同样含一个 STORE 指令及若干 LOAD 指令

把代码中的内存屏障去掉

kfifo_len()
out = LOAD fifo->out
/* smp_rmb() */
len = LOAD fifo->in - out kfifo_in() kfifo_out() kfifo_len() kfifo_len() /* smp_mb() */ /* smp_rmb() */ off = LOAD fifo->in + off off = LOAD fifo->out + off /* memcpy */ /* memcpy */ /* smp_wmb() */ /* smp_mb() */ STORE fifo->in += off STORE fifo->out += off

两个函数的内存访问的会产生干扰的操作位于 kfifo_len() 中,假设现在是单生产者单消费者模式,考虑下面的情况

        kfifo_in()
t1 out = LOAD fifo->out
t2 /* smp_rmb() */
t3 len = LOAD fifo->in - out
t4 /* smp_mb() */ kfifo_out()
t5 off = LOAD fifo->in + off out = LOAD fifo->out
t6 /* memcpy */ /* smp_rmb() */
t7 /* smp_wmb() */ len = LOAD fifo->in - out
t8 STORE fifo->in += off /* smp_rmb() */
t9 off = LOAD fifo->out + off
t10 /* memcpy */
t11 /* smp_mb() */
t12 STORE fifo->out += off kfifo_out()
t1 out = LOAD fifo->out
t2 /* smp_rmb() */
t3 len = LOAD fifo->in - out
t4 /* smp_rmb() */ kfifo_in()
t5 off = LOAD fifo->out + off out = LOAD fifo->out
t6 /* memcpy */ /* smp_rmb() */
t7 /* smp_mb() */ len = LOAD fifo->in - out
t8 STORE fifo->out += off /* smp_mb() */
t9 off = LOAD fifo->in + off
t10 /* memcpy */
t11 /* smp_wmb() */
t12 STORE fifo->in += off

后执行的函数在 t8 时刻,实际上内存已经写入或者读出,但是 in 和 out 并没有发生改变就被另外一个函数读取。
而这并不会产生错误,但是写入或者读出的数据都比实时的数据偏小,这也是 kfifo 的高明之处。
如果出队入队的操作特别频繁的话,对结果没影响。

若是要保持实时的顺序,即 t6 -> t8,一个函数的 memcpy 操作立刻对另一个 memcpy 可见,所以需要采取一些辅助措施来保证这个效果。

kfifo的更多相关文章

  1. 模仿Linux内核kfifo实现的循环缓存

    想实现个循环缓冲区(Circular Buffer),搜了些资料多数是基于循环队列的实现方式.使用一个变量存放缓冲区中的数据长度或者空出来一个空间来判断缓冲区是否满了.偶然间看到分析Linux内核的循 ...

  2. linux内核数据结构之kfifo

    1.前言 最近项目中用到一个环形缓冲区(ring buffer),代码是由linux内核的kfifo改过来的.缓冲区在文件系统中经常用到,通过缓冲区缓解cpu读写内存和读写磁盘的速度.例如一个进程A产 ...

  3. 内核ring buffer -- kfifo

    目前kernel的kfifo根据版本有两种形式, 早期的函数形式和现在的宏定义形式 1. 早期的(linux-3.0.56/kernel/kfifo.c) 感兴趣读者可以自己看, 源码如下: /* * ...

  4. linux内核数据结构之kfifo【转】

    1.前言 最近项目中用到一个环形缓冲区(ring buffer),代码是由linux内核的kfifo改过来的.缓冲区在文件系统中经常用到,通过缓冲区缓解cpu读写内存和读写磁盘的速度.例如一个进程A产 ...

  5. Linux内核数据结构之kfifo详解

    本文分析的原代码版本: 2.6.24.4 kfifo的定义文件: kernel/kfifo.c kfifo的头文件: include/linux/kfifo.h kfifo是内核里面的一个First ...

  6. STM32 & FreeRTOS & KFIFO (巧夺天工)

    巧夺天工 的 KFIFO ,用STM32实现. 实现源文件如下: /********************************************************** * * 文件名 ...

  7. 环形缓冲区-模仿linux kfifo【转】

    转自:https://blog.csdn.net/vertor11/article/details/53741681 struct kfifo{ uint8_t *buffer; uint32_t i ...

  8. Linux内核结构体--kfifo 环状缓冲区

    转载链接:http://blog.csdn.net/yusiguyuan/article/details/41985907 1.前言 最近项目中用到一个环形缓冲区(ring buffer),代码是由L ...

  9. Linux内核中的队列 kfifo【转】

    转自:http://airekans.github.io/c/2015/10/12/linux-kernel-data-structure-kfifo#api 在内核中经常会有需要用到队列来传递数据的 ...

  10. Linux kernel kfifo分析【转】

    转自:https://zohead.com/archives/linux-kernel-kfifo/ 本文同步自(如浏览不正常请点击跳转):https://zohead.com/archives/li ...

随机推荐

  1. linux用户组相关,密码相关,文件操作,和启动级别

    一.开机重启和用户切换 注意,当关机或重启前,都应当先执行一下sync指令,把内存的数据写入磁盘,防止数据丢失. shutdown命令 shutdown -h now :立即关机 shutdown - ...

  2. js获取数组最大值或最小值

    数组对象arr中属性num最大值最小值 // 最大值 Math.max.apply(Math,arr.map(item => { return item.num })) arr.sort((a, ...

  3. Idea2019激活码

    此教程仅用作个人学习,请勿用于商业获利,造成后果自负!!! 此教程已支持最新2019.2版本 此教程实时更新,请放心使用:如果有新版本出现猪哥都会第一时间尝试激活: idea官网下载地址:http:/ ...

  4. 【ZJOI 2014】力

    Problem Description 给出 \(n\) 个数 \(q_i\),给出 \(F_j\) 的定义如下: \[F_j=\sum_{i<j} \frac{q_iq_j}{(i-j)^2} ...

  5. 查看Oracle被锁的表以及如何解锁

    注意权限问题 1.查看是否有被锁的表: select b.owner,b.object_name,a.session_id,a.locked_modefrom v$locked_object a,db ...

  6. (转)格拉布斯准则(Grubbs Criterion)处理数据异常

    格拉布斯准则:https://baike.baidu.com/item/%E6%A0%BC%E6%8B%89%E5%B8%83%E6%96%AF%E5%87%86%E5%88%99/3909586 G ...

  7. 松软科技前端课堂:JavaScript 数值方法

    Number 方法帮助您处理数值. Number 方法和属性 原始值(比如 3.14 或 2016),无法拥有属性和方法(因为它们不是对象). 但是通过 JavaScript,方法和属性也可用于原始值 ...

  8. JS基础语法----Math对象

        推荐查看MDN----在线的帮助文档 实例对象: 通过构造函数创建出来,实例化的对象 静态对象: 不需要创建,直接就是一个对象,方法(静态方法)直接通过这个对象名字调用 实例方法必须通过实例对 ...

  9. JS基础语法---JSON格式的数据

         1. 对象: 有属性和方法,特指的某个事物     对象: 一组无序属性的集合的键值对,属性的值可以是任意的类型   2.JSON格式的数据:一般都是成对的,是键值对,     json也是 ...

  10. js分号问题

    总结一句话: 一行开头是括号(比如IIFE)或者方括号的时候加上分号就可以