文件底层的深入理解(1)

简介: 文件底层的深入理解(1)

一、文件学习的简单铺垫

       我们都知道,文件等于文件内容加上文件属性。访问文件之前都得先通过进程才能打开相应的文件,一个进程可以打开多个文件。修改文件,都是通过执行代码的方式完成修改。要对文件进行修改(或其他操作),文件就必须事先被加载到内存当中。从前面的叙述我们可以知道,在一定的时间段内,系统可能呢存在多个进程,也一定会存在多个被打开的文件,操作系统通过先描述再组织的方式对这些文件进行统一的管理。所以,在操作系统内部,一定会存在描述被打开文件的结构体,并用其定义对象。没有被打开的文件就存储在磁盘当中。

二、对文件路径产生与由来的理解

       从上面的铺垫可以看出,文件与进程一定是密切相关的,下面我启动一个进程,在这个进程中创建了一个文件并向其中写入内容:

并获得该进程的pid:

       在proc目录中找到该进程对应的所有属性,其中就可以看到该进程所处的目录。进程在打开时,会自动记录它当前所处的目录,所以在该进程中创建的文件如果不带路径,那么自然而然地就被创建在了进程所在的目录中。这就是文件路径的产生与由来。

三、文件的系统调用接口

       我们都知道,上层的语言是无法直接访问底层的硬件的,要访问硬件必须通过操作系统,所以操作系统就必须提供所谓的系统调用函数来供用户使用。那为什么我们看不到系统调用函数呢?原因是因为在语言层面上已经封装了系统调用函数。就比如说fopen函数就封装了open函数。下面我会以open函数对系统调用函数做一些简单的介绍。

open函数

       我们可以看到open函数中有flags这个参数,其实flags这个参数你可以把它看成32个比特位,其中每一个比特位代表不同的权限(类似于位图),所以我们就可以通过与或操作对flags设置不同的值,进而设置文件的读写权限。

       mode是权限的意思,如果一个文件事先还没有被创建出来,就必须在创建的时候通过设置mode指明它的权限。

       O_WRONLY表示只写权限位(注意这里的只写与C语言中的w权限不一样,O_WRONLY并不会将原有的文件内容清空再写入,而是直接在文件的开头进行覆盖式写入,如果要将原有的文件内容清空再写入需要再或上O_TRUNC),O_CREAT表示文件不存在就创建权限位,0666表示我设置的权限位(也会受umask掩码的约束),如果一个文件本来就已经存在了,在打开的时候就不用传递权限了。这样也可以创建出一个文件。

四、文件描述符详解

       文件描述符就是指的上面代码中open函数返回的fd这个int类型的值。在C语言中,描述文件的FILE类型其实就是一个结构体,该结构体中封装了特定的fd。在系统当中,一定会存在多个被打开的文件,操作系统通过先描述再组织的方式(创建出struct file结构体)对这些文件进行统一的管理,而一个进程也可能会打开多个文件,所以在描述进程的task_struct结构体中就存在一个指针struct files_struct* files,这个指针指向一个结构体,在进程创建的时候这个结构体就被创建出来了,在这个结构体中包含了很多字段,其中就有一个struct file* fd_array数组(也叫做文件描述符表),保存了该进程所打开的所有文件的地址,这样,该数组的数组下标就和文件的地址产生了一一对应的关系,而这里的数组下标就是fd。

       所以我们打开文件的本质就是先在磁盘当中找到这个文件,然后将其内容和属性加载到内存当中,创建出struct file结构体,将结构体内的属性、方法、缓冲区全部初始化,再将struct file结构体链入到操作系统管理被打开的struct file结构体链表中,再将struct file结构体的地址填入到对应进程中的struct file* fd_array数组,最后将数组下标返回给用户。最后我们总结一下:其实文件描述符就是数组下标。正如下面这个图所示:

       所以现在我们就可以大致说一下,向文件中写入内容(write函数),本质就是通过fd找到对应的struct file结构体,将数据写入struct file结构体对应的缓冲区中,再由操作系统帮我们把数据写入磁盘当中。从文件中读内容(read函数),本质就是通过fd找到对应的struct file结构体,从该结构体的缓冲区中读取数据,如果缓冲区中没有对应的数据,操作系统就会从磁盘中加载对应的数据到缓冲区中,再将数据根据上层给的地址拷贝到内存当中,文件的内容就被读到了。上面所述内容在操作系统源代码中也是可以得到验证的。

五、总结:理解一切皆文件

       各个硬件在底层的读写方法肯定都是不一样的,在创建struct file结构体时,需要创建read和write两个函数指针,在调用不同的硬件时,只需要让函数指针指向不同的函数,返回的是都是read或write方法,从而屏蔽了底层硬件上的差异,使得linux下一切都可以当成文件来看待。如图所示:

相关文章
|
SQL JavaScript Java
springboot+springm vc+mybatis实现增删改查案例!
springboot+springm vc+mybatis实现增删改查案例!
|
开发框架 前端开发 JavaScript
循序渐进VUE+Element 前端应用开发(5)--- 表格列表页面的查询,列表展示和字段转义处理
循序渐进VUE+Element 前端应用开发(5)--- 表格列表页面的查询,列表展示和字段转义处理
|
关系型数据库 MySQL 数据库
深入探讨MySQL中的幻读现象:原因、影响及解决方案
**导言:** 在数据库领域中,幻读(Phantom Read)是一个常见但容易被忽视的问题。它可能会导致事务的隔离级别无法满足预期,从而引发数据一致性问题。MySQL作为广泛使用的关系型数据库,也不免遇到幻读问题。本文将深入解析MySQL中的幻读现象,探讨其原因、影响以及可能的解决方案。
2644 0
|
存储 机器学习/深度学习 人工智能
《量子AI:突破量子比特稳定性与容错性的关键瓶颈》
量子计算的发展面临量子比特稳定性和容错性的关键挑战。量子纠错技术如表面码、Steane七量子比特颜色代码等,通过编码和解码提高可靠性。硬件设计选择超导或离子阱量子比特,结合低噪声器件减少干扰。量子噪声抑制技术优化环境,降低噪声影响。拓扑量子计算利用多体系统的拓扑性质实现天然容错。量子算法优化和AI技术助力,进一步提升抗干扰能力。尽管取得进展,但要实现大规模应用仍需克服诸多挑战。
378 13
|
开发框架 文字识别 前端开发
基于百度智能云的OCR接口进行图文识别
基于百度智能云的OCR接口进行图文识别
|
人工智能 自然语言处理 IDE
提升工作效率:探索AmazonQ预览版,开发者的生成式AI助手
提升工作效率:探索AmnQ预览版,开发者的生成式AI助手
444 0
|
DataWorks 安全 Java
DataWorks产品使用合集之在Java中引入DataWorks的SDK,该怎么操作
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
433 0
|
C语言
c语言编写一个简单的计算器(有需要直接复制粘贴使用)
c语言编写一个简单的计算器(有需要直接复制粘贴使用)
1807 0
|
机器学习/深度学习 编解码 算法
【前沿解读】17篇2023淘天业务技术A类顶会论文(上)
【前沿解读】17篇2023淘天业务技术A类顶会论文(上)
698 2