【笔记】Linux内核中的循环缓冲区
1. 有关ring buffer的理解
1) ring buffer位首尾相接的buffer,即类似生活中的圆形跑道;
2) 空闲空间+数据空间=ring buffer大小
3) ring buffer的读写,类似生活中在圆形跑道上的追赶游戏,领跑者位write,追赶着为read
4) 如果read跑的太快,追上write,追赶者read要停下来,否则游戏结束。即保证没有数据空间时,不再从ring buffer中读取数据;
5) 如果write跑的太快,反过来套圈要超过read,此时领跑者write也要停下来。即保证没有空闲空间时,不再往ring buffer中写入数据;
6) 所以,read和write之间的距离总是介于开区间(0, buffer大小)
2. linux2.6内核,kfifo的理解
假设buffer的大小为size,读指针为in,写指针为out
1) 在计算机中,整型数据加到最大值后溢出会回卷到0,从头开始)
2)buffer的长度必须是2的n次幂
3) buffer空闲空间和数据空间的大小
1> 空闲空间的大小=size-in+out
2> 空闲空间的大小=in-out
2.2 对数据空间大小计算的理解
本设计总能保证in前out前面的,in跑出unsigned int边界溢出后回卷。
因为buffer的大小是2的n次幂,而unsigned int也是2的n次幂(32位机器上,n=32),一般buffer大小不会超过unsigned int大小,即unsigned int被分成m个整块(m>=1)
空闲空间=size-数据控件=size-(in-out)=size-in+out
第2种情况:(in跑到unsigned int的边界后,溢出了)
out+数据空间=in,这个等式仍然成立。
所以:空闲空间=size-in+out,亦成立
2.3 写操作分析(读操作类似,不再赘述)
2.3.1 基本情况
设落在ring buffer内写指针为__in,读指针为__out,需要写入的空间大小为len, 其中
1. __in = fifo->in % (fifo->size - 1) (读写指针都是从0开始算起)
2. __out = fifo->out % (fifo->size - 1)
3. __size = fifo->size
4. len <= 空闲空间大小
2.3.2 写指针没有回卷
这种情况下,需要写两块buffer,做两次拷贝动作,设需要写入的大小为len,第一块空闲空间大小为left1,第二块为left2,需要第一次拷贝的大小为len1,第二次拷贝的大小为len2,len1 + len2 = len:
1. left1 = _size-__in;
2. len1 = min(len, left1) = min(len, _size-__in);
3. left2 = __out;
4. len2 = len - len1
2.3.3 写指针回卷
这种情况下,需要写一块buffer,做一次拷贝动作:
1. left1 = __out - __in <= __size - __in;
2. 而写入长度len <= 空闲空间大小,所以len <= left1 <= __size - __in,所以len1 = len, len1 = min(len, __size - __in)仍然成立
3. left2 = 0;
4. len2 = 0 = len -len1
2.3.4 两种特殊情况一般化
总结以上两种情形,第一块空闲空间大小为left1,第二块为left2,需要第一次拷贝的大小为len1,第二次拷贝的大小为len2,len1 + len2 = len,则通用情况如下:
1. len <= 空闲空间大小
2. len1 = min(len, _size-__in);
3. len2 = len -len1
附:linux2.6内核,kfifo的实现代码
点击(此处)折叠或打开
- unsigned int __kfifo_put(struct kfifo *fifo,
- unsigned char *buffer, unsigned int len)
- {
- unsigned int l;
- len = min(len, fifo->size - fifo->in + fifo->out);
- /* 前提条件写入大小len不超过空闲空间大小 */
- smp_mb();
- /* 第一块写入空闲空间,大小为min(len, size-in) */
- l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
- memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
- /* 第二块写入空闲空间,大小为len-min(len, size-in) */
- memcpy(fifo->buffer, buffer + l, len - l);
- /*
- * Ensure that we add the bytes to the kfifo -before-
- * we update the fifo->in index.
- */
- smp_wmb();
- fifo->in += len;
- return len;
- }
- unsigned int __kfifo_get(struct kfifo *fifo,
- unsigned char *buffer, unsigned int len)
- {
- unsigned int l;
- len = min(len, fifo->in - fifo->out);
- /*
- * Ensure that we sample the fifo->in index -before- we
- * start removing bytes from the kfifo.
- */
- smp_rmb();
- /* first get the data from fifo->out until the end of the buffer */
- l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
- memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
- /* then get the rest (if any) from the beginning of the buffer */
- memcpy(buffer + l, fifo->buffer, len - l);
- /*
- * Ensure that we remove the bytes from the kfifo -before-
- * we update the fifo->out index.
- */
- smp_mb();
- fifo->out += len;
- return len;
- }
【笔记】Linux内核中的循环缓冲区的更多相关文章
- (笔记)Linux内核中内存相关的操作函数
linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...
- (笔记)Linux内核中ioremap映射的透彻理解
几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器.状态寄存器和数据寄存器三大类,外设的寄存器通常被连续地编址.根据CPU体系结构的不同,CPU对IO端口的编址方式有两种: (1)I ...
- Linux内核中流量控制
linux内核中提供了流量控制的相关处理功能,相关代码在net/sched目录下:而应用层上的控制是通过iproute2软件包中的tc来实现, tc和sched的关系就好象iptables和netfi ...
- Linux内核中内存cache的实现【转】
Linux内核中内存cache的实现 转自:http://blog.chinaunix.net/uid-127037-id-2919545.html 本文档的Copyleft归yfydz所有,使用 ...
- TCP/IP协议栈在Linux内核中的运行时序分析
网络程序设计调研报告 TCP/IP协议栈在Linux内核中的运行时序分析 姓名:柴浩宇 学号:SA20225105 班级:软设1班 2021年1月 调研要求 在深入理解Linux内核任务调度(中断处理 ...
- 【转】在linux内核中读写文件 -- 不错
原文网址:http://blog.csdn.net/tommy_wxie/article/details/8194276 1. 序曲 在用户态,读写文件可以通过read和write这两个系统调用来完成 ...
- Linux内核中常见内存分配函数(一)
linux内核中采 用了一种同时适用于32位和64位系统的内存分页模型,对于32位系统来说,两级页表足够用了,而在x86_64系 统中,用到了四级页表. * 页全局目录(Page Global Dir ...
- Linux内核中的list用法和实现分析
这些天在思考知识体系的完整性,发现总是对消息队列的实现不满意,索性看看内核里面的链表实现形式,这篇文章就当做是学习的i笔记吧.. 内核代码中有很多的地方使用了list,而这个list的用法又跟我们平时 ...
- Linux内核中链表实现
关于双链表实现,一般教科书上定义一个双向链表节点的方法如下: struct list_node{ stuct list_node *pre; stuct list_node *next; ElemTy ...
随机推荐
- Html5怎么导出图片
其实很简单, 首先需要两个js文件 jquery.min.js html2canvas.js 直接上代码,几行就解决了 <a id="example1" onclick=&q ...
- Java中的线程--线程中的工具
这主要想写一下Java中的jdk提供的一些线程中的工具, 一.semaphore信号灯 Semaphore可以维护当前访问自身的线程个数,并提供了同步机制,使用Semaphore可以控制同时访问资源的 ...
- ios runloop学习
今天突然才之间才意识到NSTimer这样的运行方式,是在多线程中实现的循环还是在主线程中去实现的呢.当然不可能是在主线程中的while那么简单,那样什么都干不了,简单看了下NSTimer是以同步方式运 ...
- Python contenttypes组件
介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Contenttypes应用的核心是Co ...
- Python包,json&pickle,time&datetime,random模块
补充内容: 解决模块循环导入的两种方法:(不得已而为之,表示程序结构不够严谨) 将导入模块语句放在文件最下方 保证语句导入之前函数内代码能够被执行 将导入语句放进函数体内 使其不影响整个函数的运行 包 ...
- failed to execute goal org.apache.maven.plugins:maven-archetype-plugin错误解决方法
使用maven创建project时碰到如下错误: D:\codes\JSF>mvn archetype:create -DgroupId=com.tutorialspoint.test -Dar ...
- apk 解包 打包
APK应用程序的解包.修改.编辑.汉化.打包及应用 前两讲主要讲玩机的最基本的知识,集中在如何刷机.本讲是进级的内容,来谈谈与apk应用程序有关的知识,内容包括akp文件的解包.打包.反编辑.解析.汉 ...
- 【UOJ#51】【UR #4】元旦三侠的游戏(博弈论)
[UOJ#51][UR #4]元旦三侠的游戏(博弈论) 题面 UOJ 题解 考虑暴力,\(sg[a][b]\)记录\(sg\)函数值,显然可以从\(sg[a+1][b]\)和\(sg[a][b+1]\ ...
- 00031_ArrayList集合中常用的方法
1.ArrayList集合提供的一些常用方法 import java.util.ArrayList; public class ArrayListDemo01 { public static void ...
- Spring 常见错误解决方案记录
错误提示: 严重: Servlet.service() for servlet [datasync.controller.manager.SettingServlet] in context with ...