Linux上的文件系统一般来说就是EXT2或EXT3,但这篇文章并不准备一上来就直接讲它们,而希望结合Linux操作系统并从文件系统建立的基础——硬盘开始,一步步认识Linux的文件系统。
1.机械硬盘的物理存储机制现代计算机大部分文件存储功能都是由机械硬盘这种设备提供的。(现在的SSD和闪存从概念和逻辑上都部分继承自机械硬盘,所以使用机械硬盘来进行理解也是没有问题的)
机械硬盘能实现信息存储的功能基于:磁性存储介质能够被磁化,且磁化后会长久保留被磁化的状态,这种被磁化状态能够被读取出来,同时这种磁化状态还能够不断被修改,磁化正好有两个方向,所以可以表示0和1。 于是硬盘就是把这种磁性存储介质做成一个个盘片,每一个盘片上都分布着数量巨大的磁性存储单位,使用磁性读写头对盘片进行写入和读取(从原理上类似黑胶唱片的播放)。
一个硬盘中的磁性存储单位数以亿计(1T硬盘就有约80亿个),所以需要一套规则来规划信息如何存取(比如一本存储信息的书我们还会分为页,每一页从上到下从左到右读取,同时还有章节目录) 于是就有了这些物理、逻辑概念:
一个硬盘有多张盘片叠成,不同盘片有编号每张盘片上的存储颗粒成环形一圈圈地排布,每一圈称为磁道,有编号每条磁道上都有一圈存储颗粒,每512*8(512字节,0.5KB)个存储颗粒作为一个扇区,扇区是硬盘上存储的最小物理单位N个扇区可以组成簇,N取决于不同的文件系统或是文件系统的配置,簇是此文件系统中的最小存储单位所有盘面上的同一磁道构成一个圆柱,称为柱面,柱面是系统分区的最小单位磁头读写文件的时候,首先是分区读写的,由inode编号(区内唯一的编号后面介绍)找到对应的磁道和扇区,然后一个柱面一个柱面地进行读写。机械硬盘的读写控制系统是一个令人叹为观止的精密工程(一个盘面上有几亿个存储单位,每个磁道宽度不到几十纳米,磁盘每分钟上万转),同时关于读写的逻辑也是有诸多细节(比如扇区的编号并不是连续的),非常有意思,可以自行搜索文章拓展阅读。
有了硬盘并不意味着LInux可以立刻把它用来存储,还需要组合进Linux的文件体系才能被Linux使用。
2.Linux文件体系Linux以文件的形式对计算机中的数据和硬件资源进行管理,也就是彻底的一切皆文件,反映在Linux的文件类型上就是:普通文件、目录文件(也就是文件夹)、设备文件、链接文件、管道文件、套接字文件(数据通信的接口)等等。而这些种类繁多的文件被Linux使用目录树进行管理, 所谓的目录树就是以根目录(/)为主,向下呈现分支状的一种文件结构。不同于纯粹的ext2之类的文件系统,我把它称为文件体系,一切皆文件和文件目录树的资源管理方式一起构成了Linux的文件体系,让Linux操作系统可以方便使用系统资源。 所以文件系统比文件体系涵盖的内容少很多,Linux文件体系主要在于把操作系统相关的东西用文件这个载体实现:文件系统挂载在操作系统上,操作系统整个系统又放在文件系统里。但本文中文件体系的相关内容不是很多,大部分地方都可以用文件系统代替文件体系。
Linux中的文件类型那就先简单说说Linux中的文件类型,主要关注普通文件、目录文件和符号连接文件。
1.普通文件(-)
从Linux的角度来说,类似mp4、pdf、html这样应用层面上的文件类型都属于普通文件Linux用户可以根据访问权限对普通文件进行查看、更改和删除2.目录文件(d,directory file)
目录文件对于用惯Windows的用户来说不太容易理解,目录也是文件的一种目录文件包含了各自目录下的文件名和指向这些文件的指针,打开目录事实上就是打开目录文件,只要有访问权限,你就可以随意访问这些目录下的文件(普通文件的执行权限就是目录文件的访问权限),但是只有内核的进程能够修改它们虽然不能修改,但是我们能够通过vim去查看目录文件的内容3.符号链接(l,symbolic link)
这种类型的文件类似Windows中的快捷方式,是指向另一个文件的间接指针,也就是我们常说的软链接4.块设备文件(b,block)和字符设备文件(c,char)
这些文件一般隐藏在/dev目录下,在进行设备读取和外设交互时会被使用到比如磁盘光驱就是块设备文件,串口设备则属于字符设备文件系统中的所有设备要么是块设备文件,要么是字符设备文件,无一例外5.FIFO(p,pipe)
管道文件主要用于进程间通讯。比如使用mkfifo命令可以创建一个FIFO文件,启用一个进程A从FIFO文件里读数据,启动进程B往FIFO里写数据,先进先出,随写随读。6.套接字(s,socket)
用于进程间的网络通信,也可以用于本机之间的非网络通信这些文件一般隐藏在/var/run目录下,证明着相关进程的存在Linux 的文件是没有所谓的扩展名的,一个 Linux文件能不能被执行与它是否可执行的属性有关,只要你的权限中有 x ,比如[ -rwx-r-xr-x ] 就代表这个文件可以被执行,与文件名没有关系。跟在 Windows下能被执行的文件扩展名通常是 .com .exe .bat 等不同。 不过,可以被执行跟可以执行成功不一样。比如在 root 主目押下的 install.log 是一个文本文件,修改权限成为 -rwxrwxrwx 后面这个文件能够真的执行成功吗? 当然不行,因为它的内容根本就没有可以执行的数据。所以说,这个 x 代表这个文件具有可执行的能力, 但是能不能执行成功,当然就要看该文件的内容了。 虽然如此,不过我们仍然希望能从扩展名来了解该文件是什么东西,所以一般我们还是会以适当的扩展名来表示该文件是什么种类的。 所以Linux 系统上的文件名真的只是让你了解该文件可能的用途而已, 真正的执行与否仍然需要权限的规范才行。比如常见的/bin/ls 这个显示文件属性的指令要是权限被修改为无法执行,那么ls 就变成不能执行了。这种问题最常发生在文件传送的过程中。例如你在网络上下载一个可执行文件,但是偏偏在你的 Linux 系统中就是无法执行,那就可能是档案的属性被改变了。而且从网络上传送到你面前 的 Linux 系统中,文件的属性权限确实是会被改变的
更多linux内核视频教程文档资料免费领取后台私信【内核】自行获取.
Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂
Linux目录树对Linux系统和用户来说,所有可操作的计算机资源都存在于目录树这个逻辑结构中,对计算机资源的访问都可以认为是目录树的访问。就硬盘来说,所有对硬盘的访问都变成了对目录树中某个节点也就是文件夹的访问,访问时不需要知道它是硬盘还是硬盘中的文件夹。 目录树的逻辑结构也非常简单,就是从根目录(/)开始,不断向下展开各级子目录。3.硬盘分区硬盘分区是硬盘结合到文件体系的第一步,本质是「硬盘」这个物理概念转换成「区」这个逻辑概念,为下一步格式化做准备。 所以分本身并不是必须的,你完全可以把一整块硬盘作为一个区。但从数据的安全性以及系统性能角度来看,分区还是有很多用处的,所以一般都会对硬盘进行分区。讲分区就不得不先提每块硬盘上最重要的第一扇区,这个扇区中有硬盘主引导记录(Master boot record, MBR) 及分区表(partition table), 其中 MBR 占有 446 bytes,而分区表占有 64 bytes。硬盘主引导记录放有最基本的引导加载程序,是系统开机启动的关键环节,在附录中有更详细的说明。而分区表则跟分区有关,它记录了硬盘分区的相关信息,但因分区表仅有 64bytes , 所以最多只能记入四块分区(分区本身其实就是对分区表进行设置)。只能分四个区实在太少了,于是就有了扩展分区的概念,既然第一个扇区所在的分区表只能记录四条数据, 那我可否利用额外的扇区来记录更多的分区信息。 把普通可以访问的分区称为主分区,扩展分区不同于主分区,它本身并没有内容,它是为进一步逻辑分区提供空间的。在某块分区指定为扩展分区后,就可以对这块扩展分区进一步分成多个逻辑分区。操作系统规定:四块分区每块都可以是主分区或扩展分区扩展分区最多只能有一个(也没必要有多个)扩展分区可以进一步分割为多个逻辑分区扩展分区只是逻辑概念,本身不能被访问,也就是不能被格式化后作为数据访问的分区,能够作为数据访问的分区只有主分区和逻辑分区逻辑分区的数量依操作系统而不同,在 Linux 系统中,IDE 硬盘最多有 59 个逻辑分区(5 号到 63 号), SATA 硬盘则有 11 个逻辑分区(5 号到 15 号)一般给硬盘进行分区时,一个主分区一个扩展分区,然后把扩展分区划分为N个逻辑分区是最好的是否可以不要主分区呢?不知道,但好像不用管,你创建分区的时候会自动给你配置类型特殊的,你最好单独分一个swap区(内存置换空间),它独为一类,功能是:当有数据被存放在物理内存里面,但是这些数据又不是常被 CPU 所取用时,那么这些不常被使用的程序将会被丢到硬盘的 swap 置换空间当中, 而将速度较快的物理内存空间释放出来给真正需要的程序使用4.格式化我们知道Linux操作系统支持很多不同的文件系统,比如ext2、ext3、XFS、FAT等等,而Linux把对不同文件系统的访问交给了VFS(虚拟文件系统),VFS能访问和管理各种不同的文件系统。所以有了区之后就需要把它格式化成具体的文件系统以便VFS访问。标准的Linux文件系统Ext2是使用「基于inode的文件系统」我们知道一般操作系统的文件数据除了文件实际内容外, 还带有很多属性,例如 Linux 操作系统的文件权限(rwx)与文件属性(拥有者、群组、 时间参数等),文件系统通常会将属性和实际内容这两部分数据分别存放在不同的区块在基于inode的文件系统中,权限与属性放置到 inode 中,实际数据放到 data block 区块中,而且inode和data block都有编号Ext2 文件系统在此基础上
文件系统最前面有一个启动扇区(boot sector)这个启动扇区可以安装开机管理程序, 这个设计让我们能将不同的引导装载程序安装到个别的文件系统前端,而不用覆盖整个硬盘唯一的MBR, 也就是这样才能实现多重引导的功能把每个区进一步分为多个块组 (block group),每个块组有独立的inode/block体系如果文件系统高达数百 GB 时,把所有的 inode 和block 通通放在一起会因为 inode 和 block的数量太庞大,不容易管理这其实很好理解,因为分区是用户的分区,实际计算机管理时还有个最适合的大小,于是计算机会进一步的在分区中分块(但这样岂不是可能出现大文件放不了的问题?有什么机制善后吗?)每个块组实际还会分为分为6个部分,除了inode table 和 data block外还有4个附属模块,起到优化和完善系统性能的作用所以整个分区大概会这样划分:
?
首先我们要知道
每个文件(不管是一般文件还是目录文件)都会占用一个inode依据文件内容的大小来分配一个或多个block给该文件使用创建一个文件后,文件完整信息分布在3处地方,生成2个新文件:文件名记录在该文件所在目录的目录文件的block中,没有新文件生成文件属性、权限信息、记录具体内容的block编号记录在inode中,inode是新生成文件文件具体内存记录在block中,block是新生成文件因为文件名的记录是在目录的block当中,「新增/删除/更名文件名」与目录的w权限有关所以在Linux/Unix中,文件名称只是文件的一个属性,叫别名也好,叫绰号也罢,仅为了方便用户记忆和使用,但系统内部并不需要用文件名来定为文件位置,这样处理最直观的好处就是,你可以对正在使用的文件改名,换目录,甚至放到废纸篓,都不会影响当前文件的使用,这在Windows里是无法想象的。比如你打开个Word文件,然后对其进行重命名操作,Windows会告诉你门儿都没有,关闭文件先!但在Mac里就毫无压力,因为Mac的操作系统同样采用了inode的设计。创建文件过程当在ext2下建立一个一般文件时, ext2 会分配一个inode 与相对于该文件大小的block 数量给该文件
例如:假设我的一个block 为4 Kbytes ,而我要建立一个100 KBytes 的文件,那么linux 将分配一个inode 与25 个block 来储存该文件但同时请注意,由于inode 仅有12 个直接指向,因此还要多一个block 来作为区块号码的记录创建目录过程当在ext2文件系统建立一个目录时(就是新建了一个目录文件),文件系统会分配一个inode与至少一块block给该目录
inode记录该目录的相关权限与属性,并记录分配到的那块block号码而block则是记录在这个目录下的文件名与该文件对应的inode号block中还会自动生成两条记录,一条是.文件夹记录,inode指向自身,另一条是..文件夹记录,inode指向父文件夹从目录树中读取某个文件过程因为文件名是记录在目录的block当中,因此当我们要读取某个文件时,就一定会经过目录的inode与block ,然后才能够找到那个待读取文件的inode号码,最终才会读到正确的文件的block内的资料。由于目录树是由根目录开始,因此操作系统先通过挂载信息找到挂载点的inode号,由此得到根目录的inode内容,并依据该inode读取根目录的block信息,再一层一层的往下读到正确的文件。举例来说,如果我想要读取/etc/passwd 这个文件时,系统是如何读取的呢? 先看一下这个文件以及有关路径文件夹的信息:
$ ll -di / /etc /etc/passwd 128 dr-xr-x r-x . 17 root root 4096 May 4 17:56 /33595521 drwxr-x r-x . 131 root root 8192 Jun 17 00:20 /etc36628004 -rw-r-- r-- . 1 root root 2092 Jun 17 00:20 /etc/passwd
于是该文件的读取流程为:
/的inode:通过挂载点的信息找到inode号码为128的根目录inode,且inode规定的权限让我们可以读取该block的内容(有r与x)/的block:经过上个步骤取得block的号码,并找到该内容有etc/目录的inode号码(33595521)etc/的inode:读取33595521号inode得知具有r与x的权限,因此可以读取etc/的block内容etc/的block:经过上个步骤取得block号码,并找到该内容有passwd文件的inode号码(36628004)passwd的inode:读取36628004号inode得知具有r的权限,因此可以读取passwd的block内容passwd的block:最后将该block内容的资料读出来附录:开机流程和硬盘主引导记录可以稍微讲下开机流程和硬盘主引导记录(MBR,或者叫主引导分区) 一台可正常运行的计算机会在BIOS上设置一块启动硬盘,其实每块硬盘都可以作为启动盘,硬盘本身的设计提供的这种可能,这就要从硬盘上的第一个扇区说起,这个扇区中有硬盘主引导记录(Master boot record, MBR)及分区表(partition table), 其中 MBR 占有 446 bytes,而分区表则占有 64 bytes。 计算机主板上有一段写入到主板的程序BIOS,BIOS是开机之后计算机系统会主动执行的第一个程序。BIOS 会去分析计算机里面有哪些储存设备,我们以硬盘为例,BIOS 会依据使用者的设定去取得能够开机的硬盘, 并且到该硬盘里面去读取第一个扇区的MBR位置。 MBR 这个仅有 446 bytes 的硬盘容量里面会放置最基本的引导加载程序(Boot loader),它的目的是加载操作系统内核文件,由于引导加载程序是操作系统在安装的时候所提供的,所以它会认识硬盘内的文件系统格式,因此就能够读取操作系统内核文件。接下来就是内核文件的工作,也就是大家所知道癿操作系统的任务了。 所以简单说开机流程就是:
BIOS:开机主动运行的程序,会识别第一个可开机的设备MBR-引导加载程序:第一个可开机设备的第一个扇区内的主引导分区中的引导加载程序,可读取操作系统内核文件操作系统内核文件:不同的操作系统中关于开启自己的程序由上面的说明我们会知道,BIOS和MBR 都是硬件本身会支持的功能,到MBR中的Boot loader 则是操作系统写在 MBR 上面的一段程序了。由于 MBR 仅有 446 bytes,因此这个引导加载程序是非常小而美的,它的主要任务有:
提供菜单:用户可以选择不同的开机项目,这也是多重引导的重要功能载入操作系统内核:直接指向可开机的程序区段来启动操作系统转交其他 loader:将引导加载功能转交给其他 loader 负责这点很有趣,表示你的计算机系统里面可能具有两个以上的引导加载程序有可能吗?我们的硬盘不是只有一个 MBR 而已?是这样,但是引导加载程序除了可以安 装在 MBR 之外, 还可以安装在每个分区的引导扇区(boot sector)内分区的引导扇区这个特色造就了『多重引导』的功能(具体可以看鸟哥的书第三章第四节)机械硬盘物理存储结构拓展阅读蒋致诚. 硬盘驱动器巨磁电阻 (GMR) 磁头: 从微米到纳米[J]. 物理, 2004, 33(07): 0-0.近年来电脑硬盘存储密度的飞速增长最关键的因素是自旋阀纳米多层膜结构,即巨磁电阻(GMR)读传感器磁头的应用。巨磁电阻磁头读传感器已经实现由微电子器件向纳米电子器件转化,这一过程包含了自旋电子学、材料科学、微电子工程学、化学、微机械力学和工程学等诸学科和相关微加工技术综合性挑战极限。磁盘工作原理揭秘 http://www.dostor.com/article/2012-09-07/1712853.shtml大多数永久性或半永久性电脑数据都是将磁盘上的一小片金属物质磁化来实现。然后再将这些磁性图可被转换成原始数据。机械硬盘内部硬件结构和工作原理详解 http://blog.csdn.net/coslay/article/details/42215409给扇区编号的最简单方法是l,2,3,4,5,6等顺序编号。如果扇区按顺序绕着磁道依次编号,那么,控制器在处理一个扇区的数据期间,磁盘旋转太远,超过扇区间的间隔(这个间隔很小),控制器要读出或写入的下一扇区已经通过磁头,也许是相当大的一段距离。在这种情况下,磁盘控制器就只能等待磁盘再次旋转几乎一周,才能使得需要的扇区到达磁头下面。这就很浪费时间了。许多年前,IBM的一位杰出工程师想出了一个绝妙的办法,即对扇区不使用顺序编号,而是使用一个交叉因子(interleave)进行编号。格式化的其他细节每种操作系统能够使用的文件系统并不相同。举例来说,windows 98 以前的微 软操作系统主要利用的文件系统是 FAT (或 FAT16),windows 2000 以后的版本有所谓的 NTFS 文件系统,至于 Linux 的正统文件系统则为Ext2 (Linux second extended file system, ext2fs) 这一个。而且在默认的情况下,windows 操作系统是不会认识 Linux的Ext2的。传统的磁盘与文件系统的应用中,一个分区只能够被格式化成为一个文件系统,所以我们可以说 一个 文件系统 就是一个分区。但是由于新技术的利用,例如我们常听到的 LVM 与软件磁盘阵列(software raid), 这些技术可以将一个分区格式化为多个文件系统,也能够将多个分区合成一个文件系统,所以说,目前我们在格式化时已经不再说成针对分区来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区。inode/block 与文件大小的关系(有趣)我们简单分析一下EXT2 的inode / block 与文件大小的关系。inode 要记录的资料非常多,但偏偏又只有128bytes , 而inode 记录一个block 号码要花掉4byte ,假设我一个文件有400MB 且每个block 为4K 时, 那么至少也要十万条block 号码的记录!inode 哪有这么多空间来存储?为此我们的系统很聪明的将inode 记录block 号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区。这是啥?我们将inode 的结构画一下好了。
上图最左边为inode本身(128 bytes),里面有12个直接指向block号码的对照,这12条记录就能够直接取得block号码啦!至于所谓的间接就是再拿一个block来当作记录block号码的记录区,如果文件太大时,就会使用间接的block来记录号码。如上图中间接只是拿一个block来记录额外的号码而已。同理,如果文件持续长大,那么就会利用所谓的双间接,第一个block仅再指出下一个记录号码的block在哪里,实际记录的在第二个block当中。依此类推,三间接就是利用第三层block来记录号码啦! 这样子inode 能够指定多少个block 呢?我们以较小的1K block 来说明好了,可以指定的情况如下:
12个直接指向: 12*1K=12K由于是直接指向,所以总共可记录12笔记录,因此总额大小为如上所示间接: 256*1K=256K每笔block号码的记录会花去4bytes,因此1K的大小能够记录256笔记录,因此一个间接可以记录的文件大小如上;双间接: 2562561K=256 2 K 第一层block会指定256个第二层,每个第二层可以指定256个号码,因此总额大小如上;三间接: 256256256*1K=256 3 K 第一层block会指定256个第二层,每个第二层可以指定256个第三层,每个第三层可以指定256个号码,因此总额大小如上;总额:将直接、间接、双间接、三间接加总,得到12 + 256 + 256256 + 256256*256 (K) = 16GB此时我们知道当文件系统将block格式化为1K大小时,能够容纳的最大文件为16GB,比较一下文件系统限制表的结果可发现是一致的!但这个方法不能用在2K及4K block大小的计算中,因为大于2K的block将会受到Ext2文件系统本身的限制,所以计算的结果会不太符合文件系统大小与磁盘读取性能关于文件系统的使用效率,当你的一个文件系统规划的很大时,例如100GB这么大时,由于磁盘上的资料总是来来去去的,所以,整个文件系统上面的文件通常无法连续写在一起(block号码不连续),而是填入式的将资料填入没有被使用的block当中。如果文件写入的block真的分的很散,此时就会有所谓的文件资料离散的问题发生了。 如前所述,虽然我们的ext2 在inode 处已经将该文件所记录的block 号码都记上了, 所以资料可以一次性读取,但是如果文件真的太过离散,确实还是会发生读取效率低的问题。因为磁盘读取头还是得要在整个文件系统中来来去去的频繁读取!果真如此,那么可以将整个文件系统内的资料全部复制出来,将该文件系统重新格式化, 再将资料给他复制回去即可解决这个问题。 此外,如果文件系统真的太大了,那么当一个文件分别记录在这个文件系统的最前面与最后面的block 号码中, 此时会造成磁碟的机械手臂移动幅度过大(不是还会分块吗?),也会造成资料读取效能的低落。而且读取头在搜寻整个文件系统时, 也会花费比较多的时间去搜寻。因此分区的规划并不是越大越好, 而是真的要针对你的主机用途来进行规划才行。
Linux的一切皆文件Linux 中的各种事物比如像文档、目录(Mac OS X 和 Windows 系统下称之为文件夹)、键盘、监视器、硬盘、可移动媒体设备、打印机、调制解调器、虚拟终端,还有进程间通信(IPC)和网络通信等输入/输出资源都是定义在文件系统空间下的字节流。 一切都可看作是文件,其最显著的好处是对于上面所列出的输入/输出资源,只需要相同的一套 Linux 工具、实用程序和 API。你可以使用同一套api(read, write)和工具(cat , 重定向, 管道)来处理unix中大多数的资源. 设计一个系统的终极目标往往就是要找到原子操作,一旦锁定了原子操作,设计工作就会变得简单而有序。“文件”作为一个抽象概念,其原子操作非常简单,只有读和写,这无疑是一个非常好的模型。通过这个模型,API的设计可以化繁为简,用户可以使用通用的方式去访问任何资源,自有相应的中间件做好对底层的适配。 现代操作系统为解决信息能独立于进程之外被长期存储引入了文件,文件作为进程创建信息的逻辑单元可被多个进程并发使用。在 UNIX 系统中,操作系统为磁盘上的文本与图像、鼠标与键盘等输入设备及网络交互等 I/O 操作设计了一组通用 API,使他们被处理时均可统一使用字节流方式。换言之,UNIX 系统中除进程之外的一切皆是文件,而 Linux 保持了这一特性。为了便于文件的管理,Linux 还引入了目录(有时亦被称为文件夹)这一概念。目录使文件可被分类管理,且目录的引入使 Linux 的文件系统形成一个层级结构的目录树