Linux学习笔记之文件读取过程
0x00 概述
对于Linux系统来说,一切的数据都起源于磁盘中存储的文件。Linux文件系统的结构及其在磁盘中是如何存储的?操作系统是怎样找到这些文件进行读取的?这一章主要围绕这几个问题进行介绍(以Ext2文件系统(传统的linux文件系统)为例)。
0x01 Linux系统目录树
linux文件系统所有文件和目录都是由根目录开始的,以树的形式展开,如下图所示:

根据FHS的基本定义,根目录下面的各个目录(如usr,var)基本上都有其特定的意义,在此不多做介绍。重点说一下根目录'/'的作用和意义:
- 其他所有目录都是由根目录衍生出来的。
- 根目录中包含了开机软件、系统内核文件、函数库、文件系统修复程序等。
因此,根目录(/)所在的分区应该越小越好,应用程序所安装的软件最好不要与根目录存放在同一个分区。根目录越小,系统性能会更好,根目录所在的文件系统也较不容易出现问题。
0x02 文件(目录)存储方式
linux中,磁盘(硬盘)上的存储划分如下图所示:

- MBR: 主引导分区。
- 自举块(引导分区Boot Sector):分区中文件系统自身引导程序存放的地方。
- 超级块(Super block): 记录整个文件系统相关的信息的地方,它记录的信息主要有:block与inode的总量、使用量、剩余量,文件系统的挂载时间,最近一次写入数据的时间等。
- 柱面组(块组) 每个柱面为一个柱面组(组号与柱面号一致),一个分区包含多个柱面。
- 配置信息:不详。
- i节点位图(inode bitmap):每个inode结点对应位图中的一个位(这样一个字节可表示8个inode的使用情况),每个位值为0或1,表示该位所处下标对应的inode有没有被使用。
- 块位图(block bitmap):每个数据块或目录块都对应着块位图中的一个位,位的下标和块编号一一对应,每个位的值为0或1,表示该块是否已被使用。
- i节点表(数组)(inode table):每个文件或者目录都有对应的一个inode,inode放在inode table中,包括inode的编号及其对应的信息。
- i节点(inode): 存储文件相关信息(不包括文件名)。
- 数据块(data block): 存储文件具体内容。
- 目录块: 特殊一点的数据块,存放
inode编号--文件(目录)名。
inode详解
inode的主要记录了文件的属性以及该文件实际数据是放在哪几号数据块(或目录块)中,具体包含以下信息:
- 文件的访问模式(r/w/x)
- 文件所有者和组(owner/group)
- 文件大小
- 文件创建或状态改变的时间(ctime)
- 最近一次的读取时间(atime)
- 最近修改的时间(mtime)
- 定义文件特性的标志(flag)
- 文件真正内容指向的数据块(pointer)
另外,inode的特征有:
- inode的数量和大小在磁盘格式化的时候就已经固定了,除非再次格式化重新设置,否则不可改变。
- 每个inode的大小均为128Bytes。
- 每个文件仅占用一个inode。
- 文件系统能够创建(存储)的文件数量和inode的数量有关,也和磁盘大小(数据块数量)有关。
- 系统读取文件时,需要先找到inode,分析inode记录的权限与用户是否符合,若符合才可以开始实际读取数据块中的内容。
- 为了解决inode数量可能不够用的问题,操作系统将inode记录block号的区域定义为12个直接、1个间接、1个双间接、1个三间接的记录区。
- 文件IO编程中常说的文件句柄,其实就是inode编号。
0x03 文件读取过程
已读取文件/var/log/message为例,讲解读取文件messages时,从磁盘中查找/读取文件内容的过程。

- 首先系统通过挂载信息(在超级块中,位置固定)找到根目录(/)的inode编号,根目录对应的inode是固定的(通常为2号)。
- 根据根目录的inode编号(2号),在inode table中找到对应的inode信息,从inode信息中找到存储根目录信息的目录块编号,根据编号找到数据块,如图中标记为‘/’的方格,该目录块存储的信息如图中的dentry所示。
- 从目录块中存储的信息中,找到文件名(目录名)为var所对应的inode编号(2667711)。
- 在inode table中找到编号为2667711的inode信息,从该inode信息中,找到var目录存放的数据块。从var数据块存储的信息中,找到log目录对应的inode编号(267850)。
- 重复上述步骤,直至找到message文件对应的inode结点,根据inode结点中记录的message文件内容对应的数据块,从数据块中读取内容。
0x04 扇区、块(簇/数据块)、页
在操作系统数据交互过程中,经常听到扇区、块(簇/数据块)、页这几种单位,他们在数据交互过程中的意义为:
- 扇区: 磁头从磁盘中读取数据的最小单位,即磁头每次从磁盘中读取数据,都是一个扇区一个扇区读的。
- 块(簇): 操作系统与磁盘(硬盘)交互的最小数据单元(在linux系统中称为块,在windows系统中称为簇)。操作系统从硬盘中拿一块数据,即完成一次磁盘IO。块(数据块)的大小在硬盘格式化时被指定,一般有1K,2K,4K(最常用)。如果块的大小设置为4K,那么磁盘要读取8个扇区之后,才将数据块传给操作系统。另外,数据块也是DOS下数据存储的最小单元。例如,如果一个文件的大小为1K,而块的大小为4K,那么该文件还是会占用一个块,块中剩下的3K被空闲出来,不能用于存储其他数据。因此,设置块的大小时,需要考虑要存储文件的大小。
- 页: 操作系统访问内存时的最小单元,一般系统页的大小为4K(或者更大)。操作系统访问内存中的数据时,如果发现内存中没有哪个
页可以提供该数据,那么会发生缺页,系统通过页替换(从硬盘中读取数据)的方式,将数据从硬盘读取到内存页中,再返回给调用者。
总的说来,主要就是不同系统、设备间数据交互时,使用了不同的机制和概念。其中磁盘内部(磁盘驱动程序从磁盘)读取数据时,以扇区为单位;操作系统从磁盘读取数据时,以块为单位;操作系统从内存读取数据时,以页为单位。
0x05 操作系统对文件存取操作的优化
并非每次读、写文件操作都会真正地从磁盘读出或写入,那样性能难以接受。为此操作系统使用了一系列机制,提升了文件IO的性能。
缓存
不管是硬盘还是操作系统,都会对从磁盘片中读取的数据进行缓存。硬盘中的缓存一般会比较小,如十几M,操作系统中的缓存则可能大很多。系统会将常用的文件数据放到主存储器的缓冲区,以加速文件系统的读写。一般情况下,只要系统的内存够用,系统会尽可能多的将磁盘中常用的文件缓存到内存中,直至内存耗尽(这是正常现象)。比如,如果你发现在电脑上读取文件的速度达到了2G每秒,那肯定不是真的从磁盘读取的,而是从缓存读取的。所以要测试磁盘真正的读数据的速度,需要先清空系统的缓存。
异步处理
当系统加载一个文件到内存后,如果该文件没有被改动过,则在内存区段的文件数据会被标记为clean,如果是被改动了,则会标记为dirty。此时所有的文件操作还是在内存中进行,并没有写入到磁盘中。系统会不定时的将内存中设置为dirty的数据写回到磁盘,以保持磁盘与内存数据的一致性。这个过程是异步的。你也可以sync命令,将内存中的数强制写回到硬盘。
另外,要注意的是,在正常关机的情况下,关机命令会主动调用sync来将内存中的数据写入到磁盘内,但是如果非正常关机(如断电、死机),由于数据没有来得及写入到磁盘,因此重新启动可能会花费很长的时间进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损坏)。
参考
Linux学习笔记之文件读取过程的更多相关文章
- Linux 学习笔记 5 文件的下载、压缩、解压、初步认识yum
写在前面 上节我们通过简单的几组命令,已经完全的实现了文件的移动.删除.更名.以及复制,我们最常用的基本玩法,本节将带着大家学习压缩.解压的相关步骤. Linux 学习笔记 4 创建.复制.移动.文件 ...
- Linux学习笔记 -- 话说文件
文件基本属性 Linux系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限.为了保护系统的安全性,Linux系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定. 在Li ...
- Linux学习笔记之文件权限
前言: 说起文件权限,大家在windows下应该很熟悉就对文件右键属性,然后配置一点什么读写之类的权限,然后可以分配到每个的人. 对于linux 我先为大家介绍一个使用者和组和其他的概念说明一下 文件 ...
- linux学习笔记之文件类型,及目录介绍
引用A:http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/20/3033131.html 引用B:http://www.cnblogs.c ...
- Linux学习笔记:系统启动引导过程
Linux系统启动引导过程 近期发现自己在仅仅是掌握上有几个比較硬的伤: 一.知识体系碎片,比方Linux,这学点那学点,结果没有成体系,串不起来: 二.记忆时间短暂,非常多的内容学了就忘,最后的结果 ...
- Linux学习笔记11——文件I/O之二
一.文件共享 内核使用三种数据结构表示打开的文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响. 1.每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述表 2.内 ...
- Linux学习笔记05—文件与目录权限
1. 绝对路径与相对路径绝对路径:路径的写法一定由根目录 ‘/’写起,例如 /usr/local/mysql 这就是绝对路径相对路径:路径的写法不是由根目录 ‘/’写起,例如:首先用户进入到/, 然后 ...
- linux 学习笔记之文件与管理
前言: 对于windows来说,文件的系统管理都是非常简单的(这个应该有一个捂脸),通常就是重命名,复制,移动,删除,查看文件属性,查看文件内容,寻找文件.其实在图形化行中的linux也是有这样子功能 ...
- Linux学习笔记之文件与文件系统的压缩与打包
四.文件与文件系统的压缩与打包 用途: 传输时减少带宽 Linux系统常见的压缩命令 Compass(旧版压缩,并且在centOS中默认为不安装) gzip, zcat bzip2, bzcat zi ...
随机推荐
- 国内不fq安装K8S四: 安装过程中遇到的问题和解决方法
目录 4 安装过程中遇到的问题和解决方法 4.1 常见问题 4.2 常用的操作命令 4.3 比较好的博客 国内不fq安装K8S一: 安装docker 国内不fq安装K8S二: 安装kubernet 国 ...
- Linux的DNS正向解析部署
前面介绍了DNS的作用及其相关的结果.Linux服务之DNS介绍 下面开始有关DNS的服务部署.<DNS正向解析示例> 工具:虚拟机 centos7 配置:Linux IP 192.1 ...
- OpenLDAP 常用命令
OpenLDAP 常用命令 本文原始地址:https://sitoi.cn/posts/5308.html ldapsearch ldapsearch - ldap 搜索工具 ldapsearch 实 ...
- QElapsedTimer定时器记录程序执行时间
QElapedTimer类提供了一种快速计算运行时间的方法,从Qt4.7引入. QElapsedTimer类通常用于快速计算两个事件之间经过了多少时间.它的API与QTime相似,因此可以将正在使用的 ...
- Python程序 #!/usr/bin/python 的解释
关于脚本第一行的 #!/usr/bin/python 的解释,相信很多不熟悉 Linux 系统的同学需要普及这个知识,脚本语言的第一行,只对 Linux/Unix 用户适用,用来指定本脚本用什么解释器 ...
- PHP中md5()函数绕过
PHP md5()函数的简单绕过方法,该篇作为学习笔记简单记录一下. 例题 例题链接: http://ctf5.shiyanbar.com/web/houtai/ffifdyop.php ...
- django 统计表
1. 复杂版 统计,通过跨表查询和timedate模块过滤找到 from django.db.models import Count class TongJiView(View): def today ...
- 从0到1的开发,社交App 完成
内容概要 GitHub链接:GitHub链接 客户端使用Android Studio 服务端使用IDEA + SpringBoot + MyBaits 完成功能 添加好友,即时聊天,社交广场 只是一个 ...
- python 基础笔记-函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段·. 好处为: 一可以把程序中相对独立的功能模块抽取出来,减少重读代码的编写: 二是将来可以以重复的使用这些功能模块 定义一个函数 ...
- 20180610模拟赛T4——木棍
有\(N\)根木棍,每根的长度\(L\)和重量\(W\)已知.这些木棍将被一台机器一根一根地加工.机器需要一些启动时间来做准备工作,启动时间与木棍被加工的具体情况有关.启动时间遵循以下规则: 加工第一 ...