从硬件角度理解“Linux下一切皆文件“,详解用户级缓冲区

news2025/7/15 2:39:27

目录

前言

一、从硬件角度理解"Linux下一切皆文件"

从理解硬件是种“文件”到其他系统资源的抽象

二、缓冲区

1.缓冲区介绍

2.缓冲区的刷新策略

3.用户级缓冲区

这个用户级缓冲区在哪呢?

解释关于fork再加重定向“>”后数据会打印两份的原因

4.内核缓冲区简介

总结



前言

"Linux下一切皆文件",这是Linux的一个基本设置理念同时也是Linux的设计哲学所在。

这篇博客,笔者首先总结一下我自学习Linux以来,到目前自己对“Linux下一切皆文件”的感悟和理解,其次再讨论Linux中的缓冲区机制。


提示:以下是本篇文章正文内容,下面案例可供参考

一、从硬件角度理解"Linux下一切皆文件"

首先需要再次明确Linux操作系统的主要目的或者作用:

对上,方便用户使用——为用户提供稳定的、高效的、安全的使用环境。

对下,管理好计算机繁杂的软硬件资源;

其次需要明确的是文件无外乎由两部分构成:内容和属性

内容决定文件“是什么”(数据含义)。

属性决定文件的“如何用”(权限、存储、类型)。

比如一个普通文件:

他的内容是文本、二进制数据;

他的属性是文件名、权限、大小、时间戳等。

我们可以通过write、read等修改文件内容,也可以用chmod函数修改文件的权限等属性。

初识Linux:常见指令介绍,文件权限的更改,以及粘滞位的理解-CSDN博客

那么思维发散一下,我们能否将这些硬件的自身状态、操作方法抽象为“内容+属性”,并用统一的接口修改这些硬件呢?

已知的是Linux似乎正是将系统资源(如硬件设备等)抽象为文件,提供统一的文件操作接口(openreadwriteclose等)。使得无论操作对象是普通文件、目录、设备,用户都可以通过相同的文件系统与之交互。

从理解硬件是种“文件”到其他系统资源的抽象

对于计算机上诸多的硬件资源,我目前认为操作系统通过:先整理,再管理的方法管理这些硬件。

所谓先整理,在管理。这是笔者从进程PCB的创建受到的启发。OS为方便管理不同的进程会为其创建PCB,其中包含着进程的所有属性信息,那管理硬件是不是也可以通过创建某种数据结构来实现管理呢?

假设OS为方便管理各种硬件资源会为其创建某种数据结构——这里想象成某种结构体struct file,该结构体中记录着该硬件的各种属性信息和行为函数——即IO操作。

通过对冯诺依曼体系结构的抽象,将计算机抽象为存储器和其他。这个其他中包括cpu和各种硬件设备,这么划分的原因是这些硬件都要与内存进行IO操作。我们不妨暂将所有硬件的IO操作抽象为两个函数read( )和write( )。

通过上述两点,创建一个struct file结构体,其中有着各硬件的状态信息和函数行为:

struct file
{
    //内容
    int type;
    int status;
    ……
    
    //属性
    int (*write)();//函数指针
    int (*read)();
    ……
}

那么将每个硬件file实例化(与多态有些相似),再通过一个数据结构如链表将这些硬件的struct对象管理起来,如链表。

综上,当站在上层视角来看,这些硬件都是一种统一的数据,其中有着“内容+属性”,这不就是一种抽象的“文件”吗这些个文件提供统一的文件操作接口(write、read、open、close等),无论操作对象是键盘、鼠标还是其他什么硬件,用户都可以通过相同的接口与之交互。

将上述思想和方法发散到其他系统资源,同样通过“先整理,再管理”的思想,这或许是理解“Linux下一切皆文件”的思路之一吧。

问:磁盘等硬件有输入输出好理解,那如显示器等硬件不是只有输入或者只有输出吗?

答:虽然如显示器等设备没有输入操作,我们只需将其struct内部的函数指针置为NULL即可。

以上是笔者目前对“Linux下一切皆文件”的理解,若笔者有错误的认识或者读者有更深的理解,还请读者不吝赐教,在评论区中一起讨论。

二、缓冲区

1.缓冲区介绍

1)什么是缓冲区

缓冲区本质上就是一段内存。

2)为什么要有缓冲区

磁盘等存储设备物理I/O效率极低,通过引入缓冲区将多次小数据操作合并为大数据操作,从而节省数据IO时间,提升性能。

2.缓冲区的刷新策略

通过以下代码观察缓冲区:

在程序sleep的十秒之间printf不会打印,等sleep结束后才会打印。

注意printf没有带\n。

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5     printf("hello Linux");//注意没带\n
  6     sleep(10);                                                                                                                                           
  7     return 0;
  8 }

但在printf和sleep之间添加了fflsh(stdout)后,printf会立即打印。

下面是缓冲区的三种刷新策略。

1)立即刷新——无缓冲

2)行刷新——行缓冲

3)缓冲区满——全缓冲(效率最高)

有两种特殊情况缓冲区会立即刷新:

①用户强制刷新(如上述的fflush函数);

②程序退出——这也是为什么在某些集成开发环境下(如vs2022)程序时得等一会才能在控制台上看到打印结果。

3.用户级缓冲区

引子——观察下列代码在bash不同指令下的执行情况:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 int main()
  5 {
  6     printf("hello Linux\n");//注意没带\n
  7     fprintf(stdout,"hello fprintf\n");
  8     fputs("hello fpurs",stdout);
  9     const char *str="hello writie\n";
 10     write(stdout->_fileno,str,strlen(str));
 11 
 12     fork();                                                                                                                                              
 13     return 0;
 14 }

执行 . / test:

执行. / test > log.txt

可以发现. / test > log.txt比. / test多打印了几行,这多打印的全是C标准库提供的函数。

这个用户级缓冲区在哪呢?

通过观察stdout的类型,我们可以推导出FILE中不仅有文件描述符,还存在缓冲区,所有当我们想要主动刷新缓冲区时,fflush传入的是FILE*指针。

解释关于fork再加重定向“>”后数据会打印两份的原因

①没有进行>时,我们看到打印了四条数据。stdout默认采用的是行刷新,在进行fork之前三条C函数已经将数据打印到显示器上了,FILE中不在存有相应数据了;

如果我们进行了>,写入的文件不再是显示器,而是普通文件,采用的刷新策略也不再是行缓冲而是全缓冲,而这三条C打印显然不能填满缓冲区,于是数据就没有被刷新。fork函数之后紧接着就是程序退出,故当fork创建子进程后,无论父子进程谁先退出都必定会发生写时拷贝(缓冲区刷新就是修改),因此父子进程分别向log.txt中打印了数据。

至于write,他是linux系统调用,不属于C,且write用的是fd文件描述符没有使用FILE结构体,所以C提供的缓冲区中就不考虑write,因此无论那种情况write都只打印了一次。

为什么stdout标准输出默认采用行缓冲?

有关文件描述符的解释,参看:Linux中有关文件操作的系统接口,文件描述符,重定向的介绍-CSDN博客

有关fork函数和写时拷贝的解释,参看:

Linux环境下的进程创建-fork函数的使用与写时拷贝, 进程退出exit和_exit的区别,以及进程等待waitpid和status数据的提取方法-CSDN博客

4.内核缓冲区简介

1)内核缓冲区在相应文件的file_struct中。流是文件的特殊或者说流是文件的一种高级抽象。

file_struct与task_struct(PCB)一样都是内核级数据结构,在task_struct中有着指向file_struct的指针。

2)内核缓冲区的刷新策略完全由OS自主决定;

3)完整的数据刷新过程:

4)fsync函数:强制将内核缓冲区中的数据刷入磁盘。


总结

笔者水平浅薄,对于上述内容难免有疏忽疑错,还请读者多多指处。

希望本文对你有所帮助

读完点赞,手留余香~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377887.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

游戏站的几种形式

游戏站点的主要形式&#xff1a;单品游戏站、游戏盒子站与单类型游戏盒子站 随着互联网的普及和游戏产业的快速发展&#xff0c;游戏站点作为玩家获取游戏资源和信息的重要平台&#xff0c;呈现出多种形式。本文将分析三种常见的游戏站点形式&#xff1a;单品游戏站、游戏盒子站…

打造智能化军工软件工厂,破解版本管理难题

在数字化浪潮席卷全球的当下&#xff0c;军工行业正经历着前所未有的软件工业化转型。作为这一进程的核心支撑&#xff0c;软件工厂模式正在重塑军工领域的研发体系。然而&#xff0c;传统版本管理方式已难以适应现代军工软件研发的复杂需求&#xff0c;成为制约行业发展的关键…

SpringbBoot nginx代理获取用户真实IP

为了演示多级代理场景&#xff0c;我们分配了以下服务器资源&#xff1a; 10.1.9.98&#xff1a;充当客户端10.0.3.137&#xff1a;一级代理10.0.4.105&#xff1a;二级代理10.0.4.129&#xff1a;三级代理10.0.4.120&#xff1a;服务器端 各级代理配置 以下是各级代理的基本配…

allure报告自定义logo和名称

根据pytest框架&#xff0c;做自动化测试的时候&#xff0c;选择的是allure测试报告&#xff0c;这个报告是目前所有报告中功能最强大最好用的测试报告之一 我们在使用这个测试报告的时候&#xff0c;怎么样去把allure的logo和名称替换成自己公司或者自己的logo呢&#xff1f;…

【AI论文】对抗性后期训练快速文本到音频生成

摘要&#xff1a;文本到音频系统虽然性能不断提高&#xff0c;但在推理时速度很慢&#xff0c;因此对于许多创意应用来说&#xff0c;它们的延迟是不切实际的。 我们提出了对抗相对对比&#xff08;ARC&#xff09;后训练&#xff0c;这是第一个不基于蒸馏的扩散/流模型的对抗加…

测试工程师如何学会Kubernetes(k8s)容器知识

Kubernetes(K8s)作为云原生时代的关键技术之一&#xff0c;对于运维工程师、开发工程师以及测试工程师来说&#xff0c;都是一门需要掌握的重要技术。作为一名软件测试工程师&#xff0c;学习Kubernetes是一个有助于提升自动化测试、容器化测试以及云原生应用测试能力的重要过程…

遥感图像露天矿区检测数据集VOC+YOLO格式1542张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1542 标注数量(xml文件个数)&#xff1a;1542 标注数量(txt文件个数)&#xff1a;1542 …

每日Prompt:迷你 3D 建筑

提示词 3D Q版迷你风格&#xff0c;一个充满奇趣的迷你星巴克咖啡馆&#xff0c;外观就像一个巨大的外带咖啡杯&#xff0c;还有盖子和吸管。建筑共两层&#xff0c;大大的玻璃窗清晰地展示出内部温馨而精致的设计&#xff1a;木质的家具、温暖的灯光以及忙碌的咖啡师们。街道…

el-breadcrumb 面包屑第一项后面怎么写没有分隔符

<el-breadcrumb separator"/"><el-breadcrumb-item>当前位置&#xff1a;</el-breadcrumb-item><el-breadcrumb-item :to"{ path: / }">首页</el-breadcrumb-item><el-breadcrumb-item><a href"/">活…

MYSQL 高可用

目录 一 什么是MYSQL高可用 1.1 什么是MySQL高可用 1.2方案组成 1.3 优势 2.1 案例环境 二 案例实施 1.安装mysql数据库 &#xff08;1 基础环境 &#xff08;2二进制安装进行bash (3 设置配置文件 MYSQL 的配置文件跟上面编译安装的配置文件类似 &#xff08;4. 配…

【GaussDB迁移攻略】DRS支持CDC,解决大规模数据迁移挑战

目录 1 背景介绍 2 CDC的实现原理 3 DRS的CDC实现方式 4 DRS的CDC使用介绍 5 总结 1 背景介绍 随着国内各大行业数字化转型的加速&#xff0c;客户的数据同步需求越来越复杂。特别是当需要将一个源数据库的数据同时迁移到不同的目标库场景时&#xff0c;华为云通常会创建…

HoloTime:从一张图片生成可交互的4D虚拟世界——突破静态生成模型,重构VR/AR内容生产范式

引言:静态生成模型的局限与HoloTime的突破 在空间智能与虚拟内容生成领域,传统生成模型(如扩散模型)面临两大瓶颈: 静态输出:仅能生成固定视角的3D场景或局部物体动画。沉浸感缺失:无法构建用户可“走进去”的动态4D空间(时间+空间)。HoloTime 通过“图像→全景视频→…

【深度学习】#11 优化算法

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 深度学习中的优化挑战局部极小值鞍点梯度消失 凸性凸集凸函数 梯度下降一维梯度下降学习率局部极小值 多元梯度下降 随机梯度下降随机梯度更新动态学习率…

根据台账批量制作个人表

1. 前期材料准备 1&#xff09;要有 人员总的信息台账 2&#xff09;要有 个人明白卡模板 2. 开始操作 1&#xff09;打开 人员总的信息台账&#xff0c;选择所需要的数据模块&#xff1b; 2&#xff09;点击插入&#xff0c;选择数据透视表&#xff0c;按流程操作&…

LocaleContextResolver实现多语言切换-笔记

1. LocaleContextResolver功能简介 org.springframework.web.servlet.LocaleContextResolver是 Spring MVC 中用于解析和管理用户 Locale&#xff08;语言环境&#xff09; 的核心接口。 //LocaleContextResolver 接口定义 public interface LocaleContextResolver extends L…

Zephyr OS Nordic芯片的Flash 操作

目录 概述 1. 软硬件环境 1.1 软件开发环境 1.2 硬件环境 2 Flash操作库函数 2.1 nRF52832的Flash 2.2 Nordic 特有的 Flash 操作 2.2.1 nrfx_nvmc_bytes_write 函数 2.2.2 nrfx_nvmc_page_erase函数 2.2.3 nrfx_nvmc_write_done_check 函数 3 操作Flash的接口函数…

uv python 卸载

又是查了半天 官网wiki没有 网上一堆傻子胡说 uv提示也不对 AI还在这尼玛胡编乱造 开始 我原来装了这几个环境 uv python list 现在python3.7.7不需要了&#xff0c;卸载&#xff0c;直接 uv python uninstall 3.7.7 去找你自己要卸载的版本号&#xff0c;不需要整个包名复制…

浮点数截断法:四舍五入的精确模拟

理论解释&#xff1a; 1. 目标 假设 a 3.14159&#xff0c;我们想四舍五入到 小数点后两位&#xff08;即 3.14 或 3.15&#xff09;。 2. 步骤拆解 (1) a * 100 把 a 放大 100 倍&#xff0c;让小数点后两位变成整数部分&#xff1a; 3.14159 * 100 314.159 (2) 0.5 关…

技术文章:解决汇川MD500系列变频器干扰问题——GRJ9000S EMC滤波器的应用

1. 引言 汇川MD500系列变频器&#xff08;Variable Frequency Drive, VFD&#xff09;以其高性能、宽功率范围&#xff08;0.4kW-500kW&#xff09;和灵活的控制方式&#xff0c;广泛应用于工业自动化领域&#xff0c;如风机、水泵、传送带和压缩机等。然而&#xff0c;MD500系…

大模型数据分析破局之路20250512

大模型数据分析破局之路 本文面向 AI 初学者、数据分析从业者与企业技术负责人&#xff0c;围绕大模型如何为数据分析带来范式转变展开&#xff0c;从传统数据分析困境谈起&#xff0c;延伸到 LLM MCP 的协同突破&#xff0c;最终落脚在企业实践建议。 &#x1f30d; 开篇导语…