Linux系统编程:文件系统和inode

news2024/11/16 0:46:43

目录

一. 磁盘的结构和读写数据的方式

1.1 磁盘级文件和内存级文件

1.2 磁盘的物理结构

1.3 访问磁盘数据的方式

二. 磁盘文件系统

2.1 磁盘的分区管理方法

2.2 文件名和inode的关系

三. 结合文件系统对文件创建和删除的相关问题的理解

3.1 文件创建时操作系统进行的工作

3.2 文件删除时操作系统进行的工作

3.3 查看文件时操作系统进行的工作

3.4 已删除文件的恢复问题

四. 总结


一. 磁盘的结构和读写数据的方式

1.1 磁盘级文件和内存级文件

  • 内存级文件:被某个进程打开的文件,文件的内容被加载到了内存。
  • 磁盘级文件:没有被进程打开的文件,存储在磁盘。

如果设备断电,内存中的数据会丢失,但是磁盘上存储的数据依旧会被保存下来。也就是说,磁盘是一种永久性的存储介质,永久性的存储介质还有:SSD、光盘、磁带等。

磁盘,是计算机系统中唯一的机械设备。

现代笔记本电脑和很多台式机,都采用SSD来替代机械硬盘。SSD,就是我们常说的固态硬盘,它以固态电子芯片作为存储介质,相对于磁盘,SSD的读写速度更快,成本也较高。大型互联网公司的服务器,一般还是使用磁盘来存储数据。

1.2 磁盘的物理结构

一个磁盘的主要结构包括:磁盘盘片、磁头、音圈马达、主轴等。磁盘盘片用于存储数据,磁头用于从磁盘中读取数据和向磁盘中写数据。

计算机只认识二进制数据,也就是0/1,因此,只要能在磁盘盘片上读写0/1信号即可。磁盘盘片上涂有磁性物质,通过磁头放电,改变磁盘上磁性物质的正负极,从而实现数据的读写。通过磁盘上的正负极信号,来记录二进制数据,从而实现对数据的永久性存储。

图1.1 磁盘的物理结构

磁盘盘片,根据区域划分原则,可分为如下几块区域:

  • 磁道:在一个磁盘盘片上,距离中心轴半径相同的环形面。
  • 扇区:一个磁道中的一段扇形区域,每块扇区所对应的圆周角大小相同。
  • 柱面:所有磁盘盘片上,以主轴为中心轴,半径相同的圆柱面。(一个磁盘并非只有一个盘片,而是由许多盘片摞起来的)

一个扇区,为一个数据存储的单元。一般一个扇区可以存储512bytes的数据,也有些磁盘一个扇区存储4KB的数据,现在的技术也支持了不同扇区的容量有所不同。

图1.2 磁盘盘片结构

1.3 访问磁盘数据的方式

如果我们想要访问某个特定的数据,要依次进行如下的工作,找到数据存储的位置:

  1. 确定数据存储在哪个磁盘盘面(确定对应磁头)-- Head
  2. 确定位于那个磁道(柱面)-- Cylinder
  3. 确定位于哪个扇区 -- Sector 

上述寻址方法,被称为CHS寻址法, 有了CHS,我们就能够访问到任意扇区的数据。

我们可以通过磁带结构,来抽象类比磁盘。如图1.3所示,磁带被环形缠绕在一个柱面上,每层磁带叠加起来,就好比磁盘的盘片结构,磁带上也存在正负极来记录二进制信号。磁带可以展开为线性结构,这个线性结构就类似于数组,而我们可以想象将磁盘当做磁带展开,这样盘形结构就变为了数组似的线性结构。每个数组下标位置,就相当于一个磁盘上的扇区,根据下标就可以转换获取对应的盘面、磁道和扇区。

假设存储空间为1T的磁盘,那么我们就可以假想整个磁盘的存储空间就是一个数组,而向磁盘的某个扇区写数据,就等同于向这个数组中某个特定下标位置写数据。

图1.3 磁带
图1.4 磁盘盘面抽象展开图

二. 磁盘文件系统

2.1 磁盘的分区管理方法

由于一个磁盘的存储空间相对较大,为了便于管理,一般会对磁盘进行分区管理,这就好比我们将电脑的存储空间分为C盘、D盘、E盘。磁盘的存储空间,会被划分为若干个Block Group和一个Boot Block,Boot Block记录整个文件系统相关的属性信息,如果Boot Block中的数据丢失,那么对整个文件系统来说将是灾难性的,因此,在每个block group中,会有一块Super Block,用于备份文件系统的属性信息。当Boot Block中的信息丢失时,OS会去Block Group中寻找备份信息。

每个Block Group又可以根据存储数据的不同,分为这几个区域:Super Block、Group Descriptor Table、Block Bitmap、inode Bitmap、inode Table、Data Blocks。在这些分区里,存储了文件的数据和属性,以及块组和文件系统相关的属性信息。

图2.1 磁盘分区图

每块Block Group(块组)内部分区存储的内容为:

  • Data Block:数据块,存储文件的正文内容,一般来说,每个块组的容量为4KB。
  • inode Table:inode表,每个文件会分的一块128bytes的inode空间,用于存储文件的属性信息。同时,每个inode都有与之对应的inode编号,对应于某个特定的文件,如果拿到文件的inode编号,就可以找到对应的inode模块,获取文件的属性信息。
  • inode Bitmap:与inode Table对应的位图,每个二进制比特位对应一个inode Table的下标位置,0表示该inode Table位置(某个inode编号)没有被使用,1表示被使用了。
  • Block Bitmap:与Data Block对应的位图,每个存储文件内容的Data Block如果被使用了,与之对应的Block Bitmap的二进制位就为1,否则为0。
  • Group Descriptor Table:块组描述表,记录该Block Group(块组)中,使用了几个inode,还剩几个inode,使用了几个Data Block,还有多少Data Block没有使用等信息。
  • Super Block:记录整个文件系统的属性信息,如果Boot Block或某个块组上的Super Block上存储的信息被破坏,那么其他块组中的Super Block就存储了其备份信息,用于OS恢复文件系统属性信息。之所以要在多个块组保存多份文件系统属性信息,是因为如果文件系统属性信息被破坏或丢失,那么整个文件系统就会崩溃。

在磁盘的每个块组上记录上面的这些信息,让每个文件的属性和内容可追溯、可管理。在磁盘中,文件的内容和文件的属性是分开存储的,文件 = 文件内容 + 文件属性。

一个Data Block存储4KB的数据,磁盘和内存进行IO操作的基本单位为4KB,但是,一个扇区一般存储512Bytes的数据,不让一个扇区存储的数据量和磁盘和内存进行IO操作的基本单位保持一致主要出于以下两个方面考虑:(1)如果IO的基本单位太小,那么就会大幅增加IO的次数,降低计算机系统的整体效率。(2)如果让磁盘扇区大小和IO基本单位大小一致,那么如果磁盘扇区大小发生变化,那么就需要更改OS的源代码,不让它们一致,是为了实现硬件层面和软件层面的解耦,软件工程要求高内聚低耦合。

2.2 文件名和inode的关系

存储在特定块组中的每个文件,都会有一个独立的、与之对应的inode编号,通过这个inode编号,可以在inode Table中,查找到特定的下标位置,以获取文件的属性信息。

Linux系统内置的ll、stat等获取文件属性信息的指令,其底层都是通过拿到文件的inode编号,进而在inode Table中获取文件的属性信息来实现的。

那么,文件的内容又是怎样获取的呢,怎样知道某个文件的内容存储在哪个Data Block中呢?

每个Data Block,都有一个特定的编号,每个文件的inode中,会记录有文件对应的Data Block编号, 只需要根据inode中记录的Data Block编号,就可以找到与之对应的Data Block,从而找到文件的内容。如图2.2所示,inode中有一个blocks数组,记录存储这个文件内容的Data Block编号。

获取某个文件的内容的流程为:拿到文件的inode编号 -> 找到与之对应的inode -> 找到inode内部的Blocks数组,获取存储这个文件的内容Data Blocks -> 访问Data Blocks获取文件内容。 

那么,如果文件很大,需要庞大数量的Data Blocks才能放下的时候,又该怎么办呢,总不能将这些Data Blocks的编号全都放到inode中的Blocks数组中吧? -- Data Blocks中不仅可以存储文件的具体内容,也可以存储其它的Data Block编号,这个可以根据Data Blocks中记录的其他Data Block编号,找到存储了具体文件内容的Data Blocks。

图2.2 通过inode编号获取文件内容

inode中,并不会存储文件的文件名!

提问,如何通过文件名获取文件对应的inode编号呢?目录(文件夹),也属于文件,有与之对应的inode编号和Data Blocks,目录的Data Blocks中存储该目录下文件名和inode编号之间的映射关系,这就解释了为什么同一目录下不允许有同名的文件,因为如果有同名文件,就无法建立文件名与inode编号之间准确的映射关系。

在某一特定磁盘块组Data Group中,inode和Data Block的数量都是固定的。这就解释了为什么有时候明明块组中还有内存空间,但却无法成功创建新文件的现象。这有可能是因为inode Table被用完了,但Data Blocks还没用完,或者Data Blocks被用完了,但是inode Table还没有被用完。

三. 结合文件系统对文件创建和删除的相关问题的理解

3.1 文件创建时操作系统进行的工作

遍历块组的inode Bitmap,查找一个还没有被使用的inode编号,分配给新建的文件 -> 将对应的inode Bitmap的二进制为置为1 -> 向inode中写入文件的属性信息 -> 为文件分配Data Blocks,记入inode中,并将Block Bitmap中与之对应的二进制位置为1 -> 将文件名及其与inode编号之间的映射关系写入到文件所在目录对应的Data Blocks中。

3.2 文件删除时操作系统进行的工作

根据文件名,从文件所在路径的Data Blocks中获取该文件的inode编号 -> 根据inode编号,在inode Tables中,找到与之对应的inode,从inode中获取该文件占用的Data Blocks编号 -> 将inode Bitmap和Blocks Bitmap中对应的二进制位置0 -> 在文件所在的目录的Data Blocks中,解除文件名和inode编号的映射关系。

注意:删除文件不需要清除Data Blocks中的文件内容,只要改变位图标记、解除文件名和inode编号之间的映射关系即可。因此,删除一个大文件所耗费的时间远低于拷贝一个大文件的时间。

3.3 查看文件时操作系统进行的工作

根据文件名拿到与之对应的inode编号 -> 通过inode编号找到该文件的inode -> 从inode中获取存储该文件内容的Data Blocks -> 访问指定的Data Blocks,查看文件内容。

3.4 已删除文件的恢复问题

当用户删除一个文件时,OS会有记录相应的删除日志,日志中会包含文件的inode编号。由于删除文件并不会删除掉inode Tables和Data Blocks中的内容,因此,可以通过已删除文件的inode编号,获取存储文件内容的Data Blocks,这样就可以实现对删除文件的恢复。

但是,恢复删除文件有一个必要的前提:原来文件所使用的inode Tables和Data Blocks均没有被覆盖。如果被覆盖,那么文件就无法恢复,写文件、新建文件等各种操作,都有可能造成被删除文件的inode Tables和Data Blocks被覆盖,因此,如果误删了重要文件,在文件恢复之前,什么都不应该做!

四. 总结

  • 文件根据是否被进程打开,分为内存级文件和磁盘级文件。

  • 磁盘的主要结构有:盘片、磁头、主轴、音圈马达等。数据存储在磁盘盘片上,磁盘盘片被划分为一个个的磁道和扇区,一个扇区为一个磁盘存储单元。磁盘盘片上涂有磁性物质,磁性物质的正负极,代表二进制数据的0和1,磁头负责在磁盘盘片上读取数据和向磁盘写数据。

  • 通过CHS法,找到数据在磁盘中的盘片、磁道和扇区,就可以获取对应的数据。

  • 磁盘中是被分为若干个块组进行分区管理的,每个块组存储有文件的属性信息和文件的内容,文件的属性信息和内容是分开存储的,每个文件占用一个inode来存储属性信息,占用若干个Data Blocks存储文件内容。

  • 目录也是文件,与它自己的inode和Data Blocks,目录的Data Blocks中存有该目录下文件的文件名和与之对应的inode编号。

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

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

相关文章

如何给合宙ESP32-C3刷写arduino固件,arduinoIDE的配置,测试代码

视频教程 https://github.com/Yu-1120/ESP32-C3 资料下载地址 合宙ESP32-C3刷写arduino固件 然后点击安装就可以了 arduino-IDE的配置 我用的版本:2.1.1(版本不对也多大没关系) 下载安装 选择 ESP32C3 Dev Module 安装环境 配置环境&am…

二十六、传输层协议(下)

一、滑动窗口 刚才我们讨论了确认应答策略,对每一个发送的数据段,都要给一个ACK确认应答. 收到ACK后再发送下一个数据段。这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候. 既然这样一发一收的方式性能较低, 那么我们一次发送…

snpEff注释结果解读

目录 1.帮助文档 1.1 常用参数 2. 命令的用法: 3. 结果文件解读 4. SNP下游的分析 利用snpEff软件对 snp.vcf (利用gatk软件calling-snp)进行注释,运行下述命令: ## 构建好物种的数据库 java -jar /opt/snpEff/s…

基于Spring Boot的扶贫助农商城系统设计与实现(Java+spring boot+MySQL+VUE)

获取源码或者论文请私信博主 演示视频: 基于Spring Boot的扶贫助农商城系统设计与实现(Javaspring bootMySQLVUE) 使用技术: 前端:html css javascript jQuery ajax thymeleaf 微信小程序 后端:Java spr…

QTranslator语言转换

//appname的格式 例如通常为(QQ为应用的名称) QQ_en.ts或QQ_zh_CN.ts QString qmName"zh_CN"; QTranslator trans ; QString qm QString(":/translatoin/qt/appname_%1.qm").arg(qmName); auto ret trans.load(qm); Q_UNUSED(ret)…

CSS高级特性

1.CSS复合选择器 CSS复合选择器:复合选择器是由两个或多个基础选择器通过不同的方式组合而成的 1.1 标签指定式选择器:又称交集选择器,由两个选择器构成,其中第一个选择器为标记选择器,第二个为class选择器或id选择器…

【Spring core学习一】简单认识Spring是什么?

目录 1、为什么要学习Spring? 2、Spring是什么? 1、IoC是什么? 2、进一步通过代码演示理解IoC 3、怎么理解容器? 4、知道DI与IoC的区别? 1、为什么要学习Spring? 我们常说的Spring 指的是 Spring Fra…

地平线旭日x3派40pin引脚控制,点亮小灯,控制舵机

地平线旭日x3派40pin引脚控制,点亮小灯,控制舵机 引脚对照表点亮RGB小灯安装旭日X3派WiringPi使用WiringPi点亮RGB小灯使用软件PWM功能 官方用户手册中只有python控制教程,没有c语言控制教程。且官方的教程中并没有软件pwm功能。本教程在开发…

Linux——动静态库的制作和使用(实操+代码+原理介绍)

动静态库的制作和使用 1️⃣.动静态库介绍🏀静态库⚽️动态库🏈区别🏐使用动态库的优点包括:🏉 使用静态库的优点包括: 2️⃣静态库的制作🍊Q:库文件能不能有main()函数?&#x1f34…

imazing是什么软件?2023年imazing官网中文版下载

最近很小伙们,咨询兔八哥,imazing是什么软件?,今天兔八哥爱分享整理一下imazing到底是什么软件?好用吗? imazing是一款iOS设备管理软件,借助 iMazing 的独有 iOS 备份技术(无线、隐私和自动&am…

地震正演基础知识

文章目录 地震正演1. 地震正演基础知识1.1 地震波1.2 波动方程1.3 有限差分方法1.4 边界条件1.5 记录数据 2. 公式2.1 泰勒级数回顾2.2 二维声波方程(连续的偏微分方程)2.2.1 二维声波方程(连续的偏微分方程)2.2.2 离散化二维声波…

【C++】vector模拟实现

🌇个人主页:平凡的小苏 📚学习格言:命运给你一个低的起点,是想看你精彩的翻盘,而不是让你自甘堕落,脚下的路虽然难走,但我还能走,比起向阳而生,我更想尝试逆风…

Netty 为什么有如此高的性能?

文章首发地址 Netty高性能的三个主题 I/O传输模型:用什么样的通道将数据发送给对方,是BIO、NIO还是AIO,I/O传输模型在很大程度上决定了框架的性能。数据协议:采用什么样的通信协议,是HTTP还是内部私有协议。协议的选…

1767_Perl中的全词匹配

全部学习汇总: GreyZhang/perl_basic: some perl basic learning notes. (github.com) 当我在上一家公司工作的时候遇到过一个问题,为了解决软件接口的冲突我们需要把一个软件工程中的所有变量全都修改加一个前缀。我觉得用Perl处理是一个很好的注意&…

数据库作业3

1.查询student表的所有记录 2.查询student表的第2条到4条记录 3.从student表查询所有学生的学号(id)、姓名(name)和院系(department)的信息 4.从student表中查询计算机系和英语系的学生的信息 5.从student表…

pytest 通过conftest.py获取测试所有执行case断言失败的结果

conftest.py import pytest from datetime import datetimedef pytest_exception_interact(node, call, report):if report.failed:with open("error.log", "a", encoding"utf-8") as f:test_case f"测试文件:{node.nodeid} |…

备战CAIP——PTA甲级刷题

目录 引入2023年 真题1001 AB Format (20 分) 小数字相加再格式化输出1002 AB for Polynomials (25 分) 多项式相加1003 Emergency 救援最短路径和最大救援部队 引入 2023睿抗 RoboCom机器人开发者大赛CAIP编程设计赛道编程技能赛 考察知识点 https://mp.weixin.qq.com/s/lXp5…

靶机渗透之SICKOS: 1.1(解法2)

SICKOS: 1.1 靶机渗透测试是否存在shellshock构造payload获取bash权限切换shell构造pythonpayload,放置到py定时任务中开始监听py文件 靶机渗透 sudo nikto -h 192.168.133.139 -useproxy http://192.168.133.139:3128 - Nikto v2.5.0 ---------------------------…

Python应用实例(一)外星人入侵(八)

外星人入侵(八) 1.添加Play按钮1.1 创建Button类1.2 在屏幕上绘制按钮1.3 开始游戏1.4 重置游戏1.5 将play按钮切换到非活动状态1.6 隐藏鼠标光标 我们添加一个Play按钮,用于根据需要启动游戏以及在游戏结束后重启游戏,还会修改这…

FreeRTOS实时操作系统(十五)Tickless低功耗模式

系列文章 FreeRTOS实时操作系统(一)RTOS的基本概念 FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库) FreeRTOS实时操作系统(三)任务挂起与恢复 FreeRTOS实时操作系统&#x…