[Linux] 逐层深入理解文件系统 (1)—— 进程操作文件

标题:[Linux] 文件系统 (1)—— 进程操作文件

个人主页@水墨不写bug

        (图片来源于网络)

目录

 一、进程与打开的文件

 二、文件的系统调用与库函数的关系

1.系统调用open()        

三、内存中的文件描述符表

四、缓冲区的理解 

五、俯瞰IO 


正文开始:

 一、进程与打开的文件

        C/C++都提供了对文件进行操作的函数接口,想要对文件操作:无论是往文件中写入,还是从文件中读出,都需要满足一个前提条件:文件被打开。

        文件被打开,意味着文件被从磁盘中加载到内存中。进程是我们写的C/C++指令编译行成的运行起来的程序,本质是我们想要完成想要某一个任务。于是,我们不得不考虑加载到内存中的文件与进程之间的关系。

        文件是在磁盘中存储的,磁盘是一个硬件外设,对文件操作本质就是对磁盘这个硬件操作。但是用户没有权利直接向硬件写入。想要完成对硬件操作,需要 软硬件资源的管理者——操作系统的帮助。但是操作系统不相信如何用户,于是需要用操作系统提供的安全的访问操作系统数据的方式——系统调用。

        于是,我们通过分析可以推测——我们使用的

        fopen/fwrite/fread/fprintf/scanf/printf/cin/cout

等一系列的C/C++的文件操作的库函数,本质都是对系统调用的封装!

        这样一来,为了搞清楚封装的细节,我们需要先知道如何使用系统调用。

 二、文件的系统调用与库函数的关系

1.系统调用open()        

open()函数原型:

 

参数:

        pathname:想要打开的文件的名称;

        flags:打开的文件的方式选项,常见的选项有:

O_WRONLY: 以写的方式打开文件。

O_CREAT:     如果不存在就创建文件。

O_TRUNC:    每一次打开清空文件内容。

O_APPEND:打开文件之后不清空文件内容,而在后面追加。

        mode:如果成功创建了文件,文件被创建出来的默认权限设置。

返回值:

        一个整数int,被称为文件描述符(file descriptor)。

         其实,C语言的fopen函数在的不同打开方式,都对应一种flags的组合。C语言对文件打开方式有"w" "r"等等的区分,由于C语言fopen函数底层调用的还是open系统调用,所以自然会发现这样的对应关系:

         这两个调用本质都是对第一个系统调用函数open的调用,只不过第二种C语言式的函数调用对第一种系统调用进行了封装,在函数内部增加了语言级别的缓冲区等的操作,并且对返回值也进行了封装,把int类型的返回值封装成了FILE结构体指针类型的返回值。

        为什么C语言要这样做呢?别急,接下来我们对文件有了深入的理解认识之后,你就会体会到C语言的良苦用心了。


三、内存中的文件描述符表

        在上面的理解中,我们发现  系统调用open()函数  的返回值是一个整形int,对应的,我们发现  系统调用close()  函数也是通过一个int整数来关闭文件的,这非常令人费解,为什么仅仅凭借一个整数就可以操作整个文件的开关?

        在操作系统中,运行有成百上千的进程,每时每刻都有进程的创建,消亡。每一个进程都可以打开文件,并且一个进程可以打开不止一个文件!这就意味着操作系统必须要有一个高效的管理打卡的文件的方式,这个方式就是:

先描述,再组织!

         在内存中,不止有进程的PCB(task_struct),还有描述文件的数据结构:文件描述符表

        我们可以暂时把文件描述符表抽象理解成一个数组,这个数组存储文件的数据。磁盘中的文件被加载到内存中,就是通过这个数组来维护的。

        而open的返回值,就是打开的文件在这个数组中对应的下标!!

 

        如上图,一个个的文件被加载到内存中后,会被存储在files_struct这个结构体数组中,这个数组就是文件描述符表!

        不同的文件存储在不同下标位置:

 

         于是每一个文件就有了一个对应的下标:fd;这也就解释了为什么操作系统为什么可以拿着一个整数来对文件进行操作:因为操作系统可以通过一个整数下标来标识一个文件。

 


         当我们一次性打开并关闭多个文件,重复几次,会发现fd的分配规则:

                1)fd的0,1,2被默认提前分配为标准输入(键盘),标准输出(显示器),标准错误(显示器)。(C语言的stdin,stdout,stderr本质也是对这三个文件的封装)

               2)fd的分配机制是按照从小到大的顺序分配fd下标。

 


四、缓冲区的理解 

        语言有语言的缓冲区,系统有系统的缓冲区,这两个缓冲区存在的目的都是为了提高IO效率:

        1)因为访问外设与CPU的速度相比非常慢,所以系统缓冲区存在的意义就是尽量减少对外设的访问,当向缓冲区写入一定量的数据之后,操作系统会一次性把数据刷新到磁盘中。 

                

         2)系统调用的使用成本比库函数要高的多,因为操作系统太忙了,每一次调用系统调用都是请求操作系统配合用户一次,频繁调用会导致效率损失。所以语言缓从区存在的意义就是尽量少调用系统调用,当我们向语言级缓冲区写入一定的数据之后,C语言函数会一次性把数据刷新到系统级缓冲区。

        


五、俯瞰IO 

        这时,我们整体俯瞰io的过程:

        当我们打开一个文件,操作系统会调用open:

        1)创建file结构体;

        2)开辟文件缓冲区内容,加载问价数据(延后)

        3)查进程的文件描述符表

        4)file地址,填入对应的表的下标中

        5)返回下标

        当我们调用fopen库函数,会在上面操作的基础上创建语言级缓冲区等操作,本质是为了改善用户体验,提高效率。

         为什么C语言要封装系统调用?

        1)提高效率,改善用户体验

        2)C语言有多个不同的在不同的平台上实现的版本,具有跨平台性。但是我们所讲的系统调用,仅仅是Linux的,对于其他操作系统就不适用了。


完·~

未经作者同意禁止转载 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python实现录屏功能

python实现录屏功能 将生成的avi文件转为mp4格式后删掉avi文件 参考感谢:https://www.cnblogs.com/peachh/p/16549254.html import os import cv2 import time import threading import numpy as np from PIL import ImageGrab from pynput import keyboard from da…

前海湾地铁A出口临时路边免费停车点探寻

​ ​我们公司不少同事下班直接从桂湾地铁步行到前海湾地铁A出口,很多人也是一样,可能是上下班高峰期停车还不如步行快?由于这条路的很多高楼大厦还没建好,一路过来可以看到不少路边停车点。以前海湾地铁A出口为例,…

数学建模算法与应用 第5章 插值与拟合方法

目录 5.1 插值方法 Matlab代码示例:线性插值 Matlab代码示例:样条插值 5.2 曲线拟合的线性最小二乘法 Matlab代码示例:线性拟合 5.3 最小二乘优化与多项式拟合 Matlab代码示例:多项式拟合 5.4 曲线拟合与函数逼近 Matlab代…

基于SSM的个性化商铺系统【附源码】

基于SSM的个性化商铺系统 效果如下: 用户登录界面 app首页界面 商品信息界面 店铺信息界面 用户功能界面 我的订单界面 后台登录界面 管理员功能界面 用户管理界面 商家管理界面 店铺信息管理界面 商家功能界面 个人中心界面 研究背景 研究背景 科学技术日新月异…

10 分钟使用豆包 MarsCode 帮我搭建一套后台管理系统

以下是「 豆包MarsCode 体验官」优秀文章,作者把梦想揉碎。 十分钟使用豆包 MarsCode 搭建后台管理项目 在这个快节奏的时代,开发者们总是希望能够快速、高效地完成项目的搭建与开发工作。无论是初创企业还是大型公司,后台管理系统都是必不可…

Redis --- 第四讲 --- 常用数据结构 --- 其他类型stream、bitmap……。补充内容scan命令。

通过前面的学习,我们已经学习了Redis最关键的五个数据结构:String、List、Hash、Set、ZSet。这五个数据结构应用广泛,频繁使用。 redis中包含的所有类型,下面将要介绍不常用的类型。 一、streams类型介绍 事件、epoll/IO多路复…

力扣56~60题

题56(中等): 分析: 显然可以贪心也可以动态规划 python代码: class Solution:def merge(self, intervals: List[List[int]]) -> List[List[int]]:s_intervalssorted(intervals,keySolution.sort_rule)res[]start…

深度解析LMS(Least Mean Squares)算法

目录 一、引言二、LMS算法简介三、LMS算法的工作原理四、LMS算法的特点五、LMS算法的应用场景六、LMS算法的局限性七、总结八、进一步探讨 一、引言 自适应滤波器是一种动态调整其参数以适应变化环境的信号处理工具,广泛应用于噪声消除、信道均衡和系统识别等领域。…

006_django基于Python的二手房源信息爬取与分析2024_l77153d4

目录 系统展示 开发背景 代码实现 项目案例 获取源码 博主介绍:CodeMentor毕业设计领航者、全网关注者30W群落,InfoQ特邀专栏作家、技术博客领航者、InfoQ新星培育计划导师、Web开发领域杰出贡献者,博客领航之星、开发者头条/腾讯云/AW…

MeshGS: Adaptive Mesh-Aligned GaussianSplatting for High-Quality Rendering 论文解读

目录 一、概述 二、相关工作 1、神经渲染 2、基于Mesh的渲染 3、基于点的渲染和高斯溅射 三、前置知识 1、SDF 2、Marching Cubes算法 四、MeshGS 1、初始化Mesh网格 2、基于Mesh的GS溅射 3、损失函数 一、概述 提出一种基于距离的高斯splatting,并且将高…

【linux】进程状态与优先级

🔥个人主页:Quitecoder 🔥专栏:linux笔记仓 目录 01.Linux的进程状态02.僵尸进程-Z(zombie)处理僵尸进程 03.孤儿进程僵尸进程与孤儿进程的区别 04.进程的阻塞、挂起和运行运行状态(Running)阻塞状态&…

【RPC】RPC、gRPC 你给我往脑子里钻啊啊!

文章目录 一、RPC1. 什么是RPC2. 为什么要用RPC2.1 常见的RPC框架 3. RPC原理3.1 RPC调用流程3.2 如何做到透明化远程服务调用3.2.1 动态代理的概念3.2.2 实现 RPC 代理 3.2.3 序列化与反序列化3.2.4 服务注册与发现3.2.5 消息中的 requestID 二、gRPC1. gRPC1.1简介1.2 gRPC特…

PCL 点云配准 KD-ICP算法(精配准)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 加载点云函数 2.1.2 构建KD树函数 2.1.3 KD-ICP配准函数 2.1.4 点云可视化函数 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接: PCL点云算法…

SpringAI快速上手

一、导入依赖 镜像&#xff08;导入maven依赖&#xff09; <repositories><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>…

Lnmp(mysql分离)(nginx 1.13.6+mysql5.5+php5.3)环境一键搭建

Lnmp&#xff08;mysql分离&#xff09;&#xff08;nginx 1.13.6mysql5.5php5.3&#xff09;环境一键搭建 如果对运维课程感兴趣&#xff0c;可以在b站上、csdn或微信视频号 上搜索我的账号&#xff1a; 运维实战课程&#xff0c;可以关注我&#xff0c;学习更多免费的运维实…

当你不会介绍自己的产品和系统时,不妨看看大厂是如何做的

当你为不知如何介绍自己的产品和系统而困惑时&#xff0c;不妨把目光投向那些大厂。 大厂就像是璀璨的灯塔&#xff0c;为我们指引着方向。 他们在介绍产品和系统时&#xff0c;犹如技艺精湛的艺术家&#xff0c;以独特的方式勾勒出一幅幅令人惊艳的画卷。 他们用富有感染力…

股票金融市场中的tick,分钟,日线数据

在金融市场中&#xff0c;股票数据的分析对于投资者来说至关重要。股票数据可以根据时间粒度的不同&#xff0c;分为几种不同的类型&#xff0c;包括Tick数据、分钟数据和日线数据。下面将详细介绍这些数据类型&#xff0c;并对比它们之间的差别。 Tick数据 Tick数据&#xf…

详述python的列表、元组、字典、集合的基本语法及其函数

目录 列表: 列表的两种创建方式&#xff1a; 列表的删除&#xff1a; 列表的三种遍历&#xff1a; 列表的基础函数&#xff1a; 列表排序的两种方式&#xff1a; 列表生成式的语法结构&#xff1a; 二维列表的遍历&#xff1a; 元组&#xff1a; 元组的创建&#xff1…

Html 标题加图标

每个网页选项卡都有一个图标&#xff1a; <meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>主页</title><link rel"icon" href"images/记事本.png&…

Spring Boot框架下JavaWeb在线考试系统的创新实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…