LWN:kernel通用的ring buffer!

【高阶】linux内核环形缓冲区ring buffer实现原理分析 1、前言 最近项目中用到一个环形缓冲区(ring buffer),代码是由linux内核的kfifo改过来的。缓冲区在文件系统中经常用到,通过缓冲区缓解cpu读写内存和读写磁盘的速度。例如一个进程A产生数据发给另外一个进程B,进程B需要对进程A传的数据进行处理并写入文件,如果B没有处理完,则A要延迟发送。为了保证进程A减少等待时间,可以在A和B之间采用一个缓冲区,A每次将数据存放在缓冲区中,B每次冲缓冲区中取。这是典型的生产者和消费者模型,缓冲区中数据满足FIFO特性,因此可以采用队列进行实现。Linux 阅读详情

关注了就能看到更多这么棒的文章哦~

A generic ring buffer for the kernel

By Jonathan Corbet
June 6, 2024
Gemini-1.5-flash translation
https://lwn.net/Articles/976836/

内核的用户空间 ABI 中不乏环形缓冲区(ring buffer);在例如 BPF、io_uring、perf 和 tracing 这些子系统中都有定义了。当然,这些环形缓冲区中的每一个都是独立的实现,它们之间没有公共接口。面对这种 ABI 泛滥,自然而然的反应就是添加另一个环形缓冲区作为通用选项;这就是 Kent Overstreet 的这个补丁系列 的目标,它添加了一套新的系统调用用于环形缓冲区。

环形缓冲区只是一个保存在内存中的循环缓冲区,它在用户空间和内核之间共享。数据流的一侧将数据写入缓冲区,而另一侧则消费数据;只要缓冲区既不会溢出(overflow)也不会下溢(underflow),数据就可以在没有任何系统调用的情况下传输。因此,添加环形缓冲区可以在数据速率相对较高的场景中实现高效的数据传输。Overstreet 认为其他内核子系统可以从环形缓冲区接口中受益,并希望能够添加这些接口而不必重新发明轮子。

用户空间接口

在用户空间方面,新提议的接口中要求把环形缓冲区始终与文件描述符相关联,因此第一步将是打开与环形缓冲区将要附加的对象(如文件、设备或管道)。然后,使用新的系统调用建立环形缓冲区:

int ringbuffer(unsigned int fd, int rw, u32 size, void *buffer);

此调用将请求创建与打开的文件描述符 fd 关联的环形缓冲区;对于读取访问, rw 应设置为零,对于写入访问,应设置为其他任何值。请求的缓冲区大小在 size 中传递。在成功返回时,缓冲区的地址将存储在 buffer 中。

请注意,由实现环形缓冲区的子系统决定是否通过创建新的缓冲区来响应此调用,或者是否将现有的缓冲区映射到调用者的地址空间。后者的目的是允许单个环形缓冲区在多个进程之间共享。

在此版本的系统调用中没有 flags 参数;这很可能在最终合并到主线之前会改。

返回的指针将指向一个内存区域,该区域从该结构的副本开始:

struct ringbuffer_ptrs {
__u32       head;
__u32       tail;
__u32       size;   /* always a power of two */
__u32       mask;   /* size - 1 */
__u32       data_offset;
};

缓冲区本身将从返回的指针开始的 data_offset 处开始;实际上,该偏移量可能总是 1 个 page。缓冲区的实际大小将存储在 size 中;如上所述,它将始终是 2 的幂,原因很快就会讲到。 head 偏移量是写入位置,而 tail 是读取位置。如果 head 和 tail 相等,则缓冲区为空。

head 和 tail 在添加或消费数据时都会无条件地递增;没有围绕循环的测试。相反,这些值必须与 mask 值进行 AND 运算以获得缓冲区的实际偏移量。这种技术消除了递增路径中分支的需要,但也意味着在使用 head 和 tail 值时需要小心。测试为空很容易,因为在这种情况下两个值始终相等。对是否已满的正确测试如下:

if ((head - tail) >= size)
    /* buffer is full, can't write to it */

(这个检测已被简化;正确编写的测试必须使用原子操作以避免访存顺序 memory-ordering 问题;有关示例,请参见 此测试程序)。

写入环形缓冲区的进程可以继续向其中馈送数据,直到缓冲区填满,此时它必须停止。写入器可以轮询 tail 值以检测读取器何时追赶上来以及是否有更多空间可用,但这效率不高。类似的情况也适用于已清空缓冲区的读取方。无论哪种方式,进程都可以使用以下方法等待情况发生变化:

int ringbuffer_wait(unsigned int fd, int rw);

其中 fd 是与环形缓冲区关联的文件描述符,=rw= 指示需要读取访问还是写入访问。无论哪种方式,调用进程都会阻塞,直到环形缓冲区的情况发生变化。指示这种变化的责任也落在用户空间;将数据放入之前为空的缓冲区的写入器,或从之前已满的缓冲区消费数据的读取器应该调用:

int ringbuffer_wakeup(unsigned int fd, int rw);

在说明信中,Overstreet 提到 ringbuffer_wait() 和 ringbuffer_wakeup() 最终可能被 futex 操作取代。此补丁 还提到了需要改进 ringbuffer_wait() 以允许超时或指定在唤醒发生之前必须写入(或读取)缓冲区的最小数据量。

内核端

要向子系统添加环形缓冲区支持,应提供 file_operations 结构中的新增的 ringbuffer() 函数:

struct ringbuffer *(/ringbuffer)(struct file /file, int rw);

此函数将在响应来自用户空间的 ringbuffer() 调用时被调用。有一整套精心记录的用于处理环形缓冲区的支持函数可供驱动程序使用,包括 ringbuffer_alloc() 用于创建环形缓冲区, ringbuffer_read_iter() 和 ringbuffer_write_iter() 用于将数据移入或移出环形缓冲区等等。此补丁 提供了一个测试驱动程序,展示了在内核空间实现环形缓冲区的基础知识。

除了测试设备之外,此补丁集中没有提交任何内核内部用户。在说明信中,Overstreet 表示第一个这样的用户将是用户空间文件系统 (FUSE) 子系统,但管道和套接字可能会随后出现。据说环形缓冲区方法的性能优势显着:“以每次 16 字节的速度从环形缓冲区读取/写入比使用 read/write 系统调用快约 7 倍”。

截至撰写本文时,还没有对此提交内容的回复。这项工作仍处于早期阶段,在被认为可以合并之前,似乎需要进行一些演变;开发人员也可能希望在内核中看到一个真正的用户。更有趣的是,展示如何使用这种抽象来实现一些现有的内核环形缓冲区接口(虽然它们现在不会改变)。如果这项工作实现了其目标,它可能(从高度乐观的角度来看)是添加到内核中的最后一个环形缓冲区接口。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

e6ec98cd2a7aaa6446290ed1835e5b3b.jpeg

环形缓冲区(ring buffer)原理与实现详解 ring buffer称作环形缓冲区,也称作环形队列(circular queue),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流。如下为环形缓冲区(ring buffer) 的概念示意图。在任务间的通信、串口数据收发、log缓存、网卡处理网络数据包、音频/视频流处理中均有环形缓冲区(ring buffer) 的应用。 阅读详情

相关推荐

如何在离线的电脑上部署一个本地Deepseek(使用ollama)

例如,如果您的显卡显存为 16GB,官方推荐使用 32b 大小的 DeepSeek 模型。请根据您的硬件配置选择适合的模型版本,以获得最佳性能。首先我们需要将ollama和chatbox的安装包,Deepseek模型文件通过U盘或者光盘的形式导入到这台不能联网的电脑上。按照时间排序,找到最大的那个文件,就是gguf格式的模型,复制出来,改名为qwen2.5-coder0.5b.gguf。:基于开源模型(如 QWEN 和 LLAMA)微调,参数量从 1.5B 到 70B 不等,适合本地硬件部署。

qq_41854911的博客 1万+

Android日志系统探究

Android的日志系统是Kernel层实现了若干个环形Buffer实现的。系统各个日志读写操作都是针对这几个RingBuffer来实现的。那就来一窥Kernel是怎么做的。相关源码是位于driver/staging/android/下面的logger.c和logger.h两个文件 1,在整个Android日志系统的位置 2,在logger.c中,入口函数 s

成长的味道 914

开源AI数字人DUIX:从零构建你的智能交互助手

本文详细介绍了如何利用开源AI数字人DUIX从零构建智能交互助手。文章阐述了DUIX作为开源项目的核心优势,包括低成本启动、低网络依赖和高度可定制性,并提供了从开发环境搭建、核心模块(AI模型、语音、形象)配置到个性化业务逻辑开发与最终部署的完整实践指南,帮助开发者快速掌握构建专属AI数字人的全流程。

weixin_29051811的博客 503

linux kernel内核、驱动日志调试方法(一)

对于正在运行的内核,所谓的core文件就是这个内核在内存中的核心映像,即/proc/kcore。proc文件系统是一种无存储的文件系统,当读其中的文件时,其内容由文件关联的读函数动态生成,当写文件时,文件所关联的写函数被调用。printk是打印内核消息的函数,printk通过附加不同日志级别(loglevel)或者说消息优先级,让printk对消息进行分类,这是与printf最大的区别,在编译时,日志级别宏会被展开为一个字符串,然后与消息本文拼接在一起,因此printk中优先级和格式字符串之间没有逗号。

rjszcb的博客 7242

CODESYS开发实战:EtherCAT总线伺服从站配置与运动控制

本文详细介绍了在CODESYS平台上进行EtherCAT总线伺服从站配置与运动控制的实战教程。内容涵盖从设备描述文件安装、主从站拓扑构建,到核心的伺服使能状态机编程、过程数据映射,以及最终实现点位运动控制的完整流程。文章旨在帮助开发者快速掌握基于CODESYS的EtherCAT总线伺服控制技术,提升工业自动化项目开发效率。

weixin_29281915的博客 327

CISP-PTE考前实操练习题

CISP-PTE考前学习练习题目,渗透测试功工程师

2301_79546223的博客 1996

Linux kernel buffer ring

参考:What are the concepts of “kernel ring buffer”, “user level”, “log level”? Ring Buffer 原始问题 个人补充:runlevel是指SysV中用于确定OS运行环境的一种技术。不过在CentOS 7.X以后就被淘汰了,老版本服务器上可能还在用。 protection ring指的是X86平台将指令集使用...

weixin_34378969的博客 356

【rotors】多旋翼无人机仿真(五)——多无人机仿真

如何创建多个无人机仿真

caiqidong321的博客 2392

我使用过的Linux命令之dmesg - 查看开机信息/打印或控制内核环形缓冲区

我使用过的Linux命令之dmesg - 查看开机信息/打印或控制内核环形缓冲区 本文链接:http://codingstandards.iteye.com/blog/837486     (转载请注明出处)   用途说明 dmesg命令用于打印Linux系统开机启动信息,kernel会将开机信息存储在ring buffer中。您若是开机时来不及查看信息,可利用dmesg来查看(prin...

巨人站在肩膀上 792

华为Atlas200DK实战指南:从零搭建AI开发环境到人像语义分割模型部署

本文提供了一份详尽的华为Atlas 200DK AI开发环境搭建与模型部署实战指南。文章采用合设环境方案,从SD卡准备、系统镜像烧录、网络配置到必备工具安装,逐步引导开发者完成环境搭建。核心部分详细讲解了如何利用华为ATC工具将TensorFlow模型转换为昇腾专用格式,并最终成功编译和运行人像语义分割模型,实现实时人像识别效果。

weixin_29309213的博客 354

理想L9高通QAM8797座舱域控制器全拆解|全网独家复现 硬件架构升级、电源散热优化、多屏低延迟交互、车机系统赋能高端智能座舱落地

随着智能汽车向舱驾一体、全域智能化、多模交互方向迭代,传统单一功能座舱芯片已无法满足多屏高刷渲染、全车AI语音、车内视觉感知、高速车载通信的叠加算力需求。2026款全新理想L9作为旗舰级智能SUV,全面搭载高通新一代旗舰座舱域控制器QAM8797,搭配自研马赫M100 AI芯片、国产车规主控芯片,构建起高性能、高可靠、低延迟的车载中央计算平台。

getusushu的博客 377

LWN:epoll也要用ring buffer来跟用户程序交互了

A ring buffer for epollByJonathan CorbetMay 30, 2019epoll这一组system call系统调用设计目的就是希望能...

Linux News搬运工 479

药物吸收仿真软件:Caco-2_(9).Caco-2模型在药物开发中的案例分析

通过以上五个案例,我们可以看到Caco-2模型在药物开发中的重要作用。它不仅能够帮助我们预测药物的肠道吸收情况,还能够用于优化药物配方、评估代谢稳定性、研究药物相互作用以及转运蛋白的影响。这些体外实验和仿真分析的结果为药物的进一步临床研究提供了重要的参考依据,有助于缩短药物开发周期,提高研发效率。

kkchenjj的博客 863

Linux内核工程师校招笔试全攻略:核心知识点与备考路线

操作系统是计算机软件体系的基石,而Linux内核则是其最核心的实现。理解进程管理、内存管理、文件系统与并发同步等基础机制,是深入底层技术的关键。内核工程师需要掌握从系统调用到硬件驱动的完整链路,包括CFS调度器、虚拟内存、RCU同步、epoll网络模型等高频考点。这些知识不仅服务于高性能服务器、云计算与容器隔离等场景,也是解决线上并发问题的重要工具。针对校招笔试,系统梳理内核核心机制、结合源码实验与场景分析训练,能将零散知识点串联成完整的解题思路。围绕Linux内核工程师岗位的考察逻辑,从操作系统原理、内核

weixin_34116482的博客 338

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

深入理解Linux网络技术内幕 P1-P2

细品

西门吹雪 539

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

linux内核数据结构之kfifo

1、前言   最近项目中用到一个环形缓冲区(ring buffer),代码是由linux内核的kfifo改过来的。缓冲区在文件系统中经常用到,通过缓冲区缓解cpu读写内存和读写磁盘的速度。例如一个进程A产生数据发给另外一个进程B,进程B需要对进程A传的数据进行处理并写入文件,如果B没有处理完,则A要延迟发送。为了保证进程A减少等待时间,可以在A和B之间采用一个缓冲区,A每次将数据存放在缓冲区中,...

weixin_34037515的博客 432

Linux ringbuffer分析

Linux源码解压后可在源码目录下Documentation/trace/ring-buffer-design.txt中找到设计。ring_buffer位于linux-5.7/include/linux/ring_buffer.h中。kfifo位于linux-5.7/include/linux/kfifo.h中。ring_buffer实际使用trace_buffer结构体,定义如下。面试被问到网卡RingBuffer数据结构,瞎猜猜错了,学习一下。本博客针对Linux5.7。

yumWant2debug的博客 699

Linux内核的是如何实现环形缓冲区机制的?

Why is printk() so complicated? https://linuxreviews.org/Why_is_printk()_so_complicated%3F 特点 它将允许在没有死锁风险的任何情况下存储和读取消息  它是一个多生产者,单个或多个消费者组成的循环缓冲区。 structkfifo{ unsignedchar*buffer; unsignedintsize; unsigned...

一口Linux的专栏 2515

linux内核--使用内核队列实现ringbuffer

ringbuffer1.instance analysis 1.instance analysis /**@brief 仿照linux kfifo写的ring buffer *@atuher Anker date:2013-12-18 * ring_buffer.h * */ #ifndef KFIFO_HEADER_H #define KFIFO_HEADER_H #include <inttypes.h> #include <string.h> #include

嵌入式与人工智能 1227

Linux内核跟踪之ring buffer的实现

分类: linux内核跟踪 ------------------------------------------ 本文系本站原创,欢迎转载! 转载请注明出处:http://ericxiao.cublog.cn/ ------------------------------------------ 一: 前言 Ring buffer是整个tra

sjx800688的专栏 1万+

dmesg 显示开机信息。

功能说明:显示开机信息。语  法:dmesg[-cn][-s<缓冲区大小>]补充说明:kernel会将开机信息存储在ringbuffer中。您若是开机时来不及查看信息,可利用dmesg来查看。开机信息亦保存在/var/log目录中,名称为dmesg的文件里。参  数: -c 显示信息后,清除ringbuffer中的内容。 -s<缓冲区大小> 预设置为8196,...

weixin_34310785的博客 681

从内核角度看网络包发送流程

释放掉RingBuffer中的数组对skb的引用(注意:此时RingBuffer里的数组虽然放弃了对skb的引用,但是该skb并不会被立即清除,因为TCP有重传机制,必须要保证收到了对方的ack应答后再彻底删除该skb,如果没有收到对方的ack,那么传输层还可以重传该skb)通过上面的两种发送数据时拷贝的对比,可以看出sendfile相比与传统的方式,一次数据发送流程中,少了一次【CPU拷贝】,两次【态的切换】,在需要发送的数据较大的情况下,这里便是性能的提升点。能,sendfile就是这么干的。

wenpan的博客 4386

linux ringbuffer原理,linux内核 使用内核队列实现ringbuffer(续)

一、ring buffer在以前的一篇文章--网络编程中接受缓冲的ringbuf的简单实现介绍了一个自己写的ringbuffer,其实原理和linux内核中的队列很相似,思想是一样的,只不过处理的没有内核那么恰当巧妙,这里也可以使用linux内核中的队列实现之。/**@brief 仿照linux kfifo写的ring buffer*@atuher Anker date:2013-12-18* ...

weixin_29592699的博客 1065

linux 内核环形缓冲区,环形缓冲区

8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?万丈高楼平地起的前提是地基好.环形缓冲区介绍圆形缓冲区(circular buffer),也称作圆形队列(circular queue),循环缓冲区(cyclic buffer),环形缓冲区(ring buffer),是一种数据结构用于表示一个固定尺寸、头尾相连的缓冲区,适合缓存数据流。用法圆形缓冲区的一个有用特性是:当...

weixin_34040270的博客 1451

[kernel]内核日志及printk结构分析

一直都知道内核printk分级机制,但是没有去了解过,前段时间和一个同事聊到开机启动打印太多,只需要设置一下等级即可;另外今天看驱动源码,也看到类似于Printk(KERN_ERR “…”)的打印信息,以前用都是直接printk("…"),今晚回来就把printk这个机制熟悉一下。 转自:http://blog.youkuaiyun.com/tangkegagalikaiwu/article/details/...

weixin_44936219的博客 1525

Ring Buffer介绍

Ring Buffer的高级用法(类似内核KFIFO) 环形缓冲区(ring buffer),环形队列(ring queue) 多用于2个线程之间传递数据,是标准的先入先出(FIFO)模型。一般来说,对于多线程共享数据,需要使用mutex来同步,这样共享数据才不至于发生不可预测的修改/读取,然而,mutex的使用也带来了额外的系统开销,ring buffer/queue 的引入,就是为了有效地解...

$好记性还是要多记录$ 2万+
上一篇: LWN:BPF 指令集架构标准化!
下一篇: LWN:丢弃文件系统的page cache!
LinuxNews搬运工
博客等级 码龄7年 438粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值