【linux】认识“文件”的本质,理解“文件系统”的设计逻辑,体会linux优雅的设计理念


⭐⭐⭐个人主页⭐⭐⭐

~~~~~~~~~~~~~~~~~~

C站最❤❤❤❤❤❤博主

~~~~~~~~~~~~~~~~~~~

​♥东洛的克莱斯韦克-CSDN博客

~~~~~~~~~~~~~~~~~~~~

嗷呜~

✌✌✌✌

萌妹统治世界~

🎉🎉🎉🎉

✈✈✈✈相关文章✈✈✈✈

💤【Linux】进程地址空间-CSDN博客💤💤💤

​​💤💤💤【linux】进程控制——进程创建,进程退出,进程等待-CSDN博客​​💤💤

【linux】在linux操作系统下快速熟悉开发环境并上手开发工具——体验不一样的开发之旅_熟悉linux下开发-CSDN博客

目录

概述

文件描述符

0 1 2 文件描述符

文件描述符分配规则

重定向原理概述

dup2系统调用

缓冲区

用户级缓冲区

内核缓冲区

缓冲区的好处

认识磁盘

磁盘的寻址

磁盘的抽象化理解

文件系统

重新认知目录

上层数据如何流动到磁盘中


概述

文件 == 内容  +  属性

文件的内容就是在文件中写入的数据

要怎么理解 “ 属性 ” 一词呢?如果有一个苹果,怎么才能认识到它是一个苹果呢,我们很难说清一个苹果的本质到底是什么,但可以通过它的形状,色泽口感来判断这是一个苹果。这就是一个苹果的属性,一个事物的属性可以帮助我们认识 “ 它 ” 是什么

文件的属性能帮我们认识一个文件

文件的基本属性可以用 ll 指令查看

一个文件的基本属性:文件类型,权限,硬链接数,拥有者,所属组,文件内容大小,最近一次被修改的时间

当我们只创建了文件,并未在文件中写入数据,该文件的大小也不为 0 。该文件的相关属性也会被保存到磁盘中。

文件会被谁访问呢?

答案是进程,进程创建文件,进程打开文件,进程对文件做写入。

认清文件的各种操作本质是认清进程和文件的关系。进程和文件之间是怎么联系起来的呢?

文件保存在哪里呢?

答案是磁盘,磁盘的物理结构是怎样的?怎么做到从从硬件层到软件层的抽象化呢?

文件是怎么被管理的呢?

答案是文件系统,什么是文件系统呢?它是怎么把文件管理起来的呢?

上述问题是该文章的主框架。此外,还会谈一谈周边问题:重定向原理,缓冲区,内存管理(基本认知),目录,以及Linux下一切皆文件的话题

回答了上述问题就可以谈一谈应用层的数据如何通过操作系统写入磁盘的

注:本文旨在让读者对文件有进一步的认知,打消对文件的零认知。并未涉及对文件系统的专业讲解以及对linux文件系统源码级理解。

文件描述符

进程要打开某个文件时,操作系统会在内存中创建file结构体来维护文件的属性。上文已经提到属性的概念。

一个进程能打开多个文件,所以进程和文件的对应关系是一对多

所以一个 task_struct(进程控制块,用来描述进程属性的结构体)可以对应多个file结构体。

task_struct中有一个指针指向一个files_struct的数组,而数组中存的是的file*类型的指针,这样就实现了一个进程对应多个文件。

files_struct数组的下标就是文件描述符

所有的操作系统提供的接口(系统调用)中只认文件描述符

有关文件系统调用接口(用法可用man手册查看):open  close  read  write  lseek

语言层对文件操作的函数和系统提供的文件接口关系如下

语言层提供的函数必须封装文件描述符和系统调用

0 1 2 文件描述符

操作系统会默认打开三个流:标准输入   标准输出   标准错误

标准输入对应键盘文件

标准输出和标准错误对应显示器文件 

为什么硬件也可以称为文件会在文章的最后谈,即linux下一切皆文件的话题

0号文件描述符代表代表键盘文件,1号和2号文件描述符代表显示器文件

files_struct数组中,0下标存的file*的指针指向键盘文件的file结构体,而1下标和2下标的的file*的指针指向显示器文件的file结构体

1号和2号文件描述符都指向显示器文件。在file结构体中会维护一个引用计数,每多一个文件描述符指向自己引用计数加加,反之减减。引用计数为 0 就释放该结构体资源。

文件描述符分配规则

files_struct数组中找最小并且未被使用的文件描述符,分配给新的file*指针。

重定向原理概述

如果关掉一号文件描述符,根据文件描述符分配规则,1号文件描述符会被分配给新创建的文件。但上层接口不知道1号描述符已经不指向显示器文件,但该接口依然会向新的文件输出。对显示器文件输出数据变成对其他文件输出数据,这种现象成为输出重定向

如果0号描述符被改变指向,本来该往显示器文件读取数据转为从其他文件读取数据,这种现象成为输入重定向

如下是输出重定向代码示例

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
int main()
{close(1);int fd = open("myfile", O_WRONLY|O_CREAT, 00644);if(fd < 0){perror("open");return 1;}printf("fd: %d\n", fd);fflush(stdout);close(fd);exit(0);
}

dup2系统调用

头文件 :#include <unistd.h>
函数原型 :int dup2(int oldfd, int newfd);

功能:把oldfd文件描述符的file*指针拷贝给newfd文件描述符的file*指针,可以不用关闭文件描述符也能完成输入,输出重定向

代码示例

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {int fd = open("./log", O_CREAT | O_RDWR);if (fd < 0) {perror("open");return 1;}close(1);dup2(fd, 1);for (;;) {char buf[1024] = {0};ssize_t read_size = read(0, buf, sizeof(buf) - 1);if (read_size < 0) {perror("read");break;}printf("%s", buf);fflush(stdout);}return 0;
}

缓冲区

缓冲区刷新策略:

1.直接刷新     2.按行刷新     3.缓冲区满了在刷新    4.进程退出时强制刷新

用户级缓冲区

在C语言中,对文件操作时都绕不开一个东西——FILE

FILE是一个结构体,里面封装了文件描述符用户缓冲区的相关的属性。

可以在/usr/include/stdio.h查看, typedef struct _IO_FILE FILE
struct _IO_FILE {int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags//缓冲区相关/* The following pointers correspond to the C++ streambuf protocol. *//* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr; /* Current read pointer */char* _IO_read_end; /* End of get area. */char* _IO_read_base; /* Start of putback+get area. */char* _IO_write_base; /* Start of put area. */char* _IO_write_ptr; /* Current put pointer. */char* _IO_write_end; /* End of put area. */char* _IO_buf_base; /* Start of reserve area. */char* _IO_buf_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封装的文件描述符
#if 0int _blksize;
#elseint _flags2;
#endif_IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/* char* _save_gptr; char* _save_egptr; */_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

内核缓冲区

用户缓冲区是由进程维护的一块空间,该缓冲区不能直接与外设交互,需要刷新到内核缓冲区,内核缓冲区与外设交互的行为叫做IO

如果通过函数向外设输出数据,该数据需要经过用户缓冲区和内核缓冲区。如果通过系统调用向外设输出信息,该数据会被直接刷到内核缓冲区。

缓冲区的好处

用户缓冲区:提高函数的效率,只需把数据交给用户缓冲区即可返回。

内核缓冲区:提高了效率,因为内核可以直接与硬件交互,而无需频繁地在用户和内核空间之间切换

认识磁盘

磁盘的重要的两个结构是盘片磁头,盘片上有磁性物质,可以记录而进程数据。磁头用来对二进制数据做存取。

盘面上可以划分为多个磁道,每个磁道又可以划分为多个扇区,,扇区是硬盘的最小的存储单元,一般是存储512字节(byte)

磁盘不仅是外设,而且还是机器设备。相同数据量下磁头移动的次数越少磁盘的效率越高。

磁盘的寻址

对磁盘上的数据做存取,首先要定位哪个盘面,然后定位哪个磁道,然后在定位哪个扇区

通过确定盘面,磁道,扇区来定位磁盘上的数据,这种寻址方式称为CHS寻址。

磁盘的抽象化理解

如果把所有磁道展开成一条直线,每个扇面在这条直线上均匀分布。像数组一般,每个扇面都有唯一的编号。这种编号的方式称为 LBA寻址

 LBA地址=(柱面编号×硬盘磁头的总数+磁头编号)×扇区数+扇区编号-1
扇区数为每磁道的扇区数

文件系统

已经可以通过LBA地址访问磁盘中的数据,那么怎么管理这些数据呢

磁盘大小

 台式机和笔记本电脑中使用的传统机械硬盘的容量范围很广,从几百GB到数十TB不等。常见的容量包括1 TB、2 TB、4 TB、8 TB乃至更大

磁盘的分区

指的是将一个物理磁盘的存储空间逻辑地划分为多个独立的部分。每个这样的部分被称为一个分区,它在操作系统中表现为一个单独的驱动器或卷。分区允许用户组织数据,例如,可以将操作系统、应用程序和用户数据分别存储在不同的分区上,这样即使某个分区出现问题,其他分区的数据仍然可以保持安全

举个简单的例子,在Windows系统下,所谓的C盘,D盘,E盘等就属于磁盘的分区

block
Linux ext2文件系统,磁盘是典型的块设备,硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。 只需管理好每一个block就可以管理好整个磁盘的数据了

怎么管理好一个block呢

介绍
Super Block 超级块, 存放文件系统本身的结构信息。
记录的信息主要有:bolck inode 的总量,未使用的block inode 的数量,一个 block inode 的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block 的信息被破坏,可以说整个文件系统结构就被破坏了
Group Descriptor Table :块组描述符,描述块组属性信息
Block Bitmap Block Bitmap 中记录着 Data Block 中哪个数据块已经被占用,哪个数据块没有被占用
inode Bitmap :每个 bit 表示一个 inode 是否空闲可用
inode Table 节点表, 存放文件属性 如 文件大小,所有者,最近修改时间等
Data blocks :数据区,存放文件内容
详解
Data blocks中存放的是文件的内容,以 八个扇区为一个数据块(大小是4KB),每个数据块都有自己的编号。

inode Table是一张节点表,每个节点对应一个文件的属性。每一个文件属性只对应一个inode,系统会为每个inode分配一个唯一的编号。

文件内容和文件属性是分开管理的。那么怎么通过inode找到在Data blocks 中的数据呢?

inode结构体中不仅会维护文件的属性,还会维护一个数组。数组的大小为15。数组中存的是Data blocks中的数据块编号,0到11下标的编号为一级索引,12下标和13下标的编号为二级索引,14号下标的编号为三级索引。

一级索引:对应的数据块的内容就是文件的内容

二级索引:对应的数据块的内容是一级索引的数据块的编号

三级索引:对应的数据块的内容是二级索引的数据块的编号

如下是简单的示意图,细节部分并不准确,仅供参考

Block Bitmap中用比特位映射的方式(位图)来代表哪一个数据块是否被使用,1代表使用,0代表未使用

inode Bitmap中用比特位映射的方式(位图)来代表哪一个inode是否被使用,1代表使用,0代表未使用

Super Block用来记录整个分区文件系统的情况,它不会在每一个block中保存但会有备份

删除文件

在计算机中,删除 == 可以被覆盖

把一个文件删除时,并不会对文件对应的数据块做写入,也就是不会对文件的内容做清空。操作系统只会把Block Bitmapinode Bitmap中位图的由 1 置 0 即可,所以一个被删除的文件是可以被恢复出来的,因为文件的内容并未被清空。

创建文件

核心工作如下:
在inode表中找到找空闲的inode,在这个inode中填入文件的属性
在数据块中写入 (如果有写入需求)
把位图中相关的信息由0 置 1
格式化
格式化的工作是把文件系统中  Super Block Group Descriptor TableBlock Bitmapinode Bitmapinode Table,的相关字段恢复为初始状态 。但中 Data blocks的数据块不会被写入,所以,即使整个磁盘被格式化了,其数据也可以恢复出来。(理论上哦~   代价比较大)

重新认知目录

目录文件的数据块中存的是文件名和inode编号的映射

linux中不会根据一个文件名查找一个文件,只会通过inode编号查找这个文件。

但我们只给了系统路径和文件名,它是怎么找到该文件的呢?

想要找到当前目录下的文件,就需要知道当前目录和inode编号的映射关系,因此就必须读取当前目录的数据块。那就需要找到当前目录的inode,因此就必须读取上级目录的数据块,因此就必须知道上级目录的inode,以此类推到根目录,根目录的文件名和inode的关系是确定的,就能找到根目录,并读取根目录的数据块,然后就能找到下级目录的inode,进而读取下级目录的数据块,一直向下推,直到找到目标文件的inode编号。

这样的递归式的寻找会有效率上的问题,所以系统会把常用的目录缓存起来,这个缓存叫dentry缓冲

操作系统会把相关文件系统的字段加载到内存,用用结构体维护起来,然后用链表维护起来,这样做是为了加速查找,不然查找文件的时候就需要先从磁盘读取,速度太慢。

上层数据如何流动到磁盘中

调用printf向显示器文件输出数据。数据会被刷到用户缓冲区。

在file结构体中会有一个指针指向address_space结构体,该结构体中会维护一颗字典树,用来建立数据和内存的映射关系,按4KB大小建立映射。然后被刷入内存缓冲区

被刷入缓冲区的数据需要建立IO请求,缓冲区中有很多IO请求,每一个请求会用结构维护起来,再用配套的算法使这些数据以最小的代价刷入磁盘——因为磁盘使机器设备

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

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

相关文章

如何使用 AutoDL 云实例基于LangChain-Chatchat 和 ChatGLM 搭建本地知识库模型详细教程(更新中)

注册 AutoDL 算力云 AutoDL算力云是一个专注于提供人工智能&#xff08;AI&#xff09;和深度学习&#xff08;DL&#xff09;领域算力资源的云计算平台。它整合了高性能计算资源&#xff0c;如GPU和TPU等&#xff0c;为用户提供了弹性、高效且成本效益高的计算服务。通过Auto…

靠谱放心!康姿百德柔压磁性豪华枕质量大揭秘

康姿百德柔压磁性豪华枕&#xff0c;舒爽透气呵护青春期娇嫩肌肤 良好的睡眠对青少年的生长发育至关重要&#xff0c;想要获得高质量睡眠&#xff0c;除了选择合适的床垫之外&#xff0c;一款合适的枕头同样是打造优质睡眠环境的重要一环。康姿百德集团有限公司深耕睡眠领域已…

《Fundamentals of Power Electronics》——理想变压器基本公式推导

接下去推导理想变压器的基本公式。理想变压器满足以下三个条件&#xff1a; 1、无铜损。假设原副边线圈均无纯电阻&#xff0c;则不会因在铜导线中产生焦耳热引起能量损耗&#xff0c;另外也不考虑回路中的分布电容。 2、无铁损。忽略通过铁芯的磁通量变化引起的涡流损耗&…

实现一个渐进优化的 Linux cp 命令

1&#xff0c;第1版 copy 先写个轮廓 selfcp.c &#xff1a; #include <stdio.h>int main() {FILE *source, *destination;char ch;source fopen("H222.txt", "r");if (source NULL) {printf("Error opening source file!\n");retur…

[算法刷题—二分法]寻找插入位置

题目展示: 本道题本身并不是很难,主要是学习和分析二分查找插入位置的方法。 首先大体上分为两种情况: 一.target在待查找的数组之中,返回对应值的下标索引。 二.target不在待查找的数组之中&#xff0c;需要返回target插入位置的索引(原数组有序) 第一种情况不难&#xff…

秋招突击——第四弹——Java的SSN框架快速入门——Maven

文章目录 引言Maven分模块开发与设计分模块开发的过程 依赖管理可选依赖与排除依赖 继承与聚合聚合继承 属性和版本管理属性扩大集中管理的范围版本管理 多环境开发多环境开发 私服简介安装私服资源操作流程分析上传和下载 总结 引言 前一个部分花了太多时间&#xff0c;后续得…

DomoAI让你轻松变身视频达人!支持20s完整视频生成!

账号注册 官网&#xff1a;https://www.domoai.app/zh-Hant/library 功能 支持不同风格的视频类型&#xff0c;支持图片转视频&#xff0c;支持文字转图片&#xff0c;支持静态图片变为动态。 可以切换语言为中文 风格转换 选择不同风格的 支持生成20s&#xff0c;目前接触…

深度学习(PyTorch)批注理解,建议边学可以边看这个笔记

前言 动手学习深度学习&#xff0c;内容丰富&#xff0c;但是对于初学者有很多晦涩难懂的地方&#xff0c;我将日常更新这篇文章以截图的形式&#xff0c;每天高强度学习四五个小时&#xff0c;精力缺乏&#xff0c;我认为&#xff0c;如果想学习这个深度学习&#xff0c;你需…

【Arthas案例】某应用依赖两个GAV不同但包含两个相同全限定类名StaticLoggerBinder,引起log4j.Level类找不到异常

3分钟内解决问题 两个不同的GAV依赖冲突&#xff0c;包含相同全限定类名&#xff0c;引起ClassNotFoundException Maven依赖的三坐标体系GAV(G-groupId&#xff0c;A-artifactId&#xff0c;V-version) 【案例1】某应用依赖两个GAV不同的jar&#xff0c;但包含两个相同全限定类…

区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测

区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测 目录 区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现BP-ABKDE的BP神经网络自适应带…

Camtasia2024破解永久激活码注册码分享最新

随着数字时代的到来&#xff0c;视频制作已成为许多人日常生活和工作中不可或缺的一部分。而在众多视频编辑软件中&#xff0c;Camtasia凭借其强大的功能和易用性&#xff0c;赢得了广泛的用户喜爱。近期&#xff0c;Camtasia 2024的破解版本在网络上引起了广泛关注。本文旨在为…

列表(list)(Python)

文章目录 一、定义二、列表常用操作 一、定义 list ["张三", "李四", "王五", "赵六"]二、列表常用操作 分类关键字/函数/方法说明增加列表.append(值)在列表末尾追加值列表.insert(索引&#xff0c; 值)在指定位置插入值&#xff…

L51--- 144. 二叉树的前序遍历(深搜)---Java版

1.题目描述 2.思路 二叉树的前序遍历遵循 根左右 &#xff08;1&#xff09;方法 preorderTraversal 输入参数: TreeNode root root是二叉树的根节点。 返回值: List 返回一个包含二叉树节点值的列表&#xff0c;这些值按照前序遍历的顺序排列。 功能: 这个方法是前序遍历的…

推荐这两款非常良心的录屏和文字转语音工具,很是让人心动,不要错过

VPot FREE 吾爱大神制作的文字转音频工具&#xff0c;免费使用。 支持英语、韩语、法语、日语等语言&#xff0c;还是支持男声、女声和儿童声音。 支持将以导入文本的格式转换成音频&#xff0c;并保存为MP3、WAV等常见的音频格式。 VPot FREE提供智能断句的功能&#xff0…

永磁同步直线电机(PMLSM)控制与仿真3-永磁同步直线电机数学三环控制整定

文章目录 1、电流环参数整定2、速度环参数整定3、位置环参数整定 写在前面&#xff1a;原本为一篇文章写完了永磁同步直线电机数学模型介绍&#xff0c;永磁同步直线电机数学模型搭建&#xff0c;以及永磁同步直线电机三环参数整定及三环仿真模型搭建&#xff0c;但因为篇幅较长…

sql优化之利用聚簇索引减少回表次数:limit 100000,10

1. 问题描述 产品&#xff1a;我要对订单列表页做一个分页功能&#xff0c;每页10条数据&#xff0c;商家可以根据金额过滤订单 技术&#xff1a;好的&#xff0c;我写一个sql实现分页&#xff0c;x表示偏移页数&#xff0c;自测limit 10,10耗时200ms&#xff1a; SELECT * …

spring boot配置ssl证书,支持https访问

1. 阿里云官网下载证书,云控制台搜索ssl&#xff0c;点击进入。 2.点击免费证书&#xff0c;立即购买。 3. 点击创建证书&#xff0c;填写完证书申请后&#xff0c;等待证书签发。 4. 证书签发以后&#xff0c;点击下载证书&#xff0c;spring boot选tomcat服务器类型的。 5. …

TCP三次握手的过程

一、什么是TCP TCP是面向连接的、可靠的、基于字节流的传输层通信协议。 二、TCP的头部格式 序列号:在建立连接时由计算机生成的随机数作为其初始值&#xff0c;通过SYN包传给接收端主机&#xff0c;每发送一次数据&#xff0c;就「累加」一次该「数据字节数」的大小。用来解…

【RAM】利用AWS Resource Access Manager服务实现与其他账户共享AWS资源

文章目录 1. 先决条件说明2. 导航至ARM控制面板3. 指定资源共享详细信息4. 关联托管式权限5. 向委托人授予访问权限6. 查看和创建7. 查看由我共享的资源8. 资源共享详细信息9. 取消关联10. 参考链接11. 生成式AI书籍推荐&#x1f4e2; 1. 先决条件说明 报错现象&#xff1a; …

视频网站下载利器yt-dlp参数详解

yt-dlp 是一个强大的命令行工具&#xff0c;用来下载 YouTube 和其他网站上的视频和音频。它拥有丰富的参数&#xff0c;可以定制下载行为&#xff0c;满足各种需求。本文将详细介绍 yt-dlp 的参数使用。 一、基本参数 -f, –format FORMAT: 指定下载格式&#xff0c;可以用视…