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. 12. Go 语言文件处理

    Go 语言文件处理 本章我们将带领大家深入了解一下 Go语言中的文件处理,重点在于文件而非目录或者通用的文件系统,特别是如何读写标准格式(如 XML 和 JSON 格式)的文件以及自定义的纯文本和二进 ...

  2. 【STM32-V7】STM32H743XIH6开发板,丰富软件资源,强劲硬件配置,大量软件解决方案持续更新中(2019-12-12)

    说明: 争取做更多的实战性应用,分享更多的嵌入式技术,希望能在实际项目中帮到大家. (1)V7将大力加强对初学者的支持力度,已经更新至63章,下载链接,后37章和一批视频教程将加紧制作. (2)事隔五 ...

  3. el-dialog模态窗点击空白不消失

    通过查阅ElementUI的官方文档,可以发现Dialog对话框组件提供了一个close-on-click-modal属性来设置el-dialog模态窗点击空白不消失. <el-dialog : ...

  4. Excel的创建和读取NPOI

    项目中经常用到需要操作Excel文件,例如:导出数据库中的数据,读取数据等.但是电脑又没有安装office,不能直接调用微软的库,最后经过查找,找到这样的一个不用安装office的库.一个.NET库, ...

  5. 记录一次Mac VSCode运行Grpc模板项目

    1.使用dotnet new grpc -o GrpcGreeter && cd GrpcGreeter && code . ,进入项目文件中,使用code .使用vs ...

  6. 下载EPM包详细运行日志

    事务码:UJFS,选择包运行的环境名称. 从root根目录下进入对应环境->模型目录,找到privatepublications 文件夹对应的账号文件夹(运行包的账号名称) 进入tempfile ...

  7. angularjs $http请求网络数据并展示

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. SpringCloud之Eureka:服务发布与调用例子

    Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的. SpringCloud将它集成在其子 ...

  9. Python-判断回文

    # 回文单词是从左到右和从右到左读相同的单词. # 例如:"detartrated"和"evitative"是回文 str_in = input('Input: ...

  10. kettle教程---通过配置表格配置实现数据的批量增量更新(实用)

    本文接上篇文章,上面文章讲的是,通过配置文件的全量更新,现在说下增量更新 如上图所示,涉及到1个转换和1个作业. 1-表增量同步(转换) 可以通过读取同步表参数这个excel表格文件,获取表名称和同步 ...