linux文件系统

发表于2017-08-28 11:41  |  次阅读  |  0条评论  |   作者:siru90

一、硬盘分区和文件系统

图1 硬盘设备上的分区和文件系统
磁盘上的的引导块是计算机加电启动时可由ROM BIOS自动读入执行的代码和数据,但并非所有盘都可以作为引导设备,所以对于不用于引导的盘片,这一盘片可以不含代码,但是任何盘片必须含有引导空间。
一块磁盘首先要分区,格式化之后才可以使用。磁盘格式化的过程实质上就是文件系统创建的过程,磁盘上的一个分区就是一个文件系统。
如我们在使用windows系统时,磁盘可以分区格式化为FAT32或者NTFS,linux可以格式化为ext2、ext3等,所格式化的系统必须是操作系统可以识别的。

二、Ext2文件系统结构详细介绍

图2  ext2文件系统整体结构 

磁盘格式时将整个盘分为固定大小的若干个block,block是管理文件系统的基础,其大小可选,ext2支持1KB、2KB、4KB,一般为1KB。
Ext2系统可分为6个block group(区块群),下面我们对着6个block group的主要内容和作用做简单说明。
在ext2文件系统中,文件由inode(包含有文件的所有信息)进行唯一标识。一个文件可能对应多个文件名,只有在所有文件名都被删除后,该文件才会被删除。此外,同一文件在磁盘中存放和被打开时所对应的inode是不同的,并由内核负责同步。
ext2文件系统采用三级间接块来存储数据块指针,并以块(block,默认为1KB)为单位分配空间。其磁盘分配策略是尽可能将逻辑相邻的文件分配到磁盘上物理相邻的块中,并尽可能将碎片分配给尽量少的文件,以从全局上提高性能。ext2文件系统将同一目录下的文件(包括目录)尽可能的放在同一个块组中,但目录则分布在各个块组中以实现负载均衡。在扩展文件时,会尽量一次性扩展8个连续块给文件(以预留空间的形式实现)。

图3  Ext2文件系统示意图
 
1、Super Block
记录文件系统的整体信息,包括inode/block总量、使用量、剩余量,block的大小、每个块组包含的块数,文件系统的格式及其他相关信息。
第一版ext2文件系统的实现里,每个Group里都存在一份superblock的副本,然而这样做的负面效果也是相当明显,那就是严重降低了磁盘的空间利用率。所以在后续ext2的实现代码中,选择用于备份superblock的Group组号的原则是3N、5N、7N其中N=0,1,2,3…。
超级块的起始位置为其所在分区的第1024个字节,占用1KB的空间,其结构如下


2、GDT
块组描述表由一个个块组描述符组成,有多少个块组就有多少描述符。块组描述表也在每个块组拥有一个备份,位置在超级块后面。块组描述符记录了一下信息:


3、Block Bitmap
关于块的位图,标识块是否被占用,简单的关系,对应bit位为1表示占用,0为空闲。Bolck Bitmap固定为一个block。

4、 Inode Bitmap
关于索引节点的位图,标识索引节点是否被占用,简单的关系,对应bit位为1表示占用,0为空闲。Inode Bitmap固定占用一个Block。
5、Inode Table:索引节点表。
6、Date Block:真正存放数据的block。
 
7、关键概念
1.1.1块组

图4  group分布图

块组和分区是完全不同的概念,分区至多只能有4个(3个主分区和1个扩展分区,如果4个分区不够用,只能用逻辑分区),分区的作用就是对磁盘进行分割,分区之后才能用文件系统对分区进行格式化;块组是基于文件系统的概念,EXT2在分区的基础上格式化后会形成至少1个以上的块组。
那么在EXT2中是用什么规则来划分块组的呢?由于EXT2规定,块位图能且只能占一个逻辑块,因此块位图事实上成为了块组划分的一个标准(或者说是限制)。

举个例子:
用EXT2格式化一个1G大小的分区,逻辑块的大小为4096字节,求此分区被格式化后有多少个块组?
如果一个Block大小为4KB,那么一个逻辑块的位图大小为:4096 * 8 = 32768,也就说一个块组最多只能有32768个逻辑块(因为块位图只能管32768个逻辑块)
32768个逻辑块的大小为:32768 * 4096 = 134217728 Bytes = 131072K Bytes = 128M Bytes
1024M Bytes / 128M Bytes = 8
因此被格式化后有8个块组,每个块组的大小为128M Bytes,编号从0开始。当然利用格式化工具,如mke2fs是可以指定块组的个数的。

1.1.2 Inode
Inode的实质是指向文件或目录的“指针”,包括文件的位置大小等,但不包括文件名。
在EXT2中,文件的数据和属性是分开保存的,文件的属性保存在Inode表中,文件的数据保存在数据块中。
一个文件(或目录项)占用一个inode,inode大于block数目是没有意义的(多出的inode没有数据块可分,浪费掉了)
linux系统在格式化分区时,默认的inode数量和数据块的数量是对应的,一般block数量不小于inode的数量,多是Inode 数量的一、二、四倍,具体数量可以用命令dumpe2fs查看,每个inode可分配的容量可以在格式化文件系统时指定。
每个inode占用128Byte,具体内容如下:

图5  inode结构图
如果每个block为1KB,那么,每个指针块可以存放4096/4=1024个指针。那么由一个二级block指针块可以索引到的数据块的数目为1024;由一个三级指针块可以索引到的数据块的数目为1024*1024,其他以此类推。

三、文件类型与存储
1. 普通文件
普通文件是最常见的,只有有数据的时候才会分配数据块。
2.目录
Ext2文件系统中,目录是作为文件存储的。根目录总是在inode表的第二项,而其子目录则在根目录文件的内容中定义。每个目录项的定义如下:

每个目录项的长度值可以大于它实际的长度,一个目录项如果有多余的空间,可以分配给其他的目录项使用,实际上目录项的窗井就是对目录空间的拆分过程,目录项的删除就是对目录空间的合并过程。
3. 连接符号
如果连接符号的路径名小于等于60个字符,就把它放在索引节点的i_block字段,该字段由15个4字节组成,因此无需数据块。但是如果大于60个字节就需要一个单独的数据块。
4.设备文件、管道和套接字
这类文件的信息放在索引节点中。

四、Ext2文件系统的挂载
1. VFS虚拟文件功能
 Linux 下的文件系统主要可分为三大块:一是上层的文件系统的系统调用,二是虚拟文件系统 VFS(Virtual Filesystem Switch),三是挂载到 VFS 中的各实际文件系统,例如 ext2等。
VFS是一种软件机制,也可以看做linux文件系统的管理者,它不是一个实际存在的文件系统,与之相关的数据只存在与物理内存。每次系统初始化的时候,都会在内存中建立一个VFS目录树(linux源代码中称之为namespace)。实际上便是在内存中建立相应的数据结构。VFS 目录树在 Linux 的文件系统模块中是个很重要的概念,不要将其与实际文件系统目录树混淆,VFS 中的各目录其主要用途在一个操作系统中支持不同类型的文件系统,提供实际文件系统的挂载点。

图6  linux中文件系统的层级结构

Vfs的功能:
u  记录操作系统可以支持和已经安装有哪些文件系统类型;
u  将相关系统调用转化为具体类型文件系统的调用;
u  负责不同类型文件系统间的协同工作(如不同fs之间的复制);
u  实现对不同类型文件系统的动态装卸和可扩充性等;
设计Vfs的目的:
u  向用户、应用程序、操作系统其他部件提供通用、统一、标准、抽象、虚拟的系统调用接口界面;
u  对应用程序等掩盖不同类型文件的差异和细节;
u  为应用程序等提供对具体文件系统类型的程序独立性和透明性。

图7  linux中文件系统的层级结构
要点:
u  /d1/f1路径上可能存在不同的文件系统,因此需要与具体文件系统交互多次。
u  文件系统类型无关的操作(大部分内存操作)进入vfs,文件系统类型相关的操作(外存操作和量内存操作)留在具体文件系统中。

2. Vfs虚拟文件系统结构
1.1.3  主要对象
VFS文件系统的基本结构是超块superblock、dentry结构体、inode结构体和file。
u  超块
内存中的超块为管理活动的(已挂载)文件系统提供必要的信息和状态。因为 Linux 支持同时挂载多个并发文件系统,所以在一个列表中维护每个 super_block 结构。File_system 全局变量fs/filesystem.c中,具有相同文件系统类型的超级块通过s_instances字段链接到文件系统类型的fs_supers字段。

uper_block 结构是指封装了其他信息的许多其他结构。例如,file_system_type 结构维护文件系统的名称(比如 ext3)以及各种锁和函数,以获取和删除 super_block。file_system_type 对象由常见的 register_file system 和 unregister_file system 函数管理(见 ./linux/fs/file systems.c)。super_operations 结构为读写节点和高级操作(比如重新挂载)定义大量函数。根目录条目(dentry)对象也缓存在这里,因为它是文件系统所在的块设备。最后,提供许多用于管理节点的列表,包括 s_inodes(列出所有节点的列表)、s_dirty(列出所有脏节点的列表)、s_io 和 s_more_io 以及 s_files(列出特定文件系统的所有打开文件的列表)。

u  dentry
文件系统的层次结构由 VFS 中的另一个称为 dentry 的对象管理。文件系统有一个根 dentry(在超块中引用),这是唯一没有父对象的 dentry。所有其他 dentry 都有父对象,并且一部分 dentry 有子对象。例如,如果打开一个由 /home/user/name 组成的文件,那么将创建 4 个 dentry 对象:一个针对根 /、一个针对根目录 home 的条目、一个针对 user 目录的 name 条目,以及一个针对 user 目录的 name 条目。通过这种方式,dentry 简洁地映射到现在使用的文件系统。
dentry 对象由 dentry 结构定义(在 ./linux/include/fs/dcache.h 中)。它由许多元素组成,这些元素在文件系统和物理数据中跟踪条目之间的关系(比如文件名)。dentry 引用 super_block,super_block 定义包含该对象的特定文件系统实例。接下来是该对象的父 dentry(父目录),其后是包含在一个列表中的子 dentry(如果该对象刚好是一个目录的话)。然后,为 dentry 定义操作(比如 hash、compare、delete 和 release 等等)。接着定义对象的名称,在这里名称保存在 dentry 中而不是 inode 中。最后,提供一个到 VFS inode 的引用。

u  Inode
Inode代表一个在磁盘上的文件,它与磁盘文件一一对应。inode 由描述 inode、inode 内容和可能在 inode 上发生的各种操作的数据和操作组成。inode 包含许多列表,其中一个列表指向引用该 inode 的 dentry。这里还包含对象级别的元数据,包括熟悉的操作时间(创建时间、访问时间和修改时间)和所有者和权限数据(组 ID、用户 ID 和权限)。inode 引用它所允许的文件操作,大部分这些操作直接映射到系统调用接口(例如,open、read、write 和 flush)。inode 还引用特定于 inode 的操作(create、lookup、link 和 mkdir 等等)。最后,对于由地址空间对象表示的对象的数据,有一个管理结构。地址空间对象 是为 inode 管理页缓存中的各种页的对象。地址空间对象用于为文件管理页,也用于将文件部分映射到独立的进程地址空间。地址空间对象有自己的操作集(writepage、readpage 和 releasepage 等等)。

Ext与VFS中都把文件管理结构称为inode,但实际上它们是不一样的。Ext的inode节点在磁盘上;VFS的inode节点在内存里。Ext-inode中的一些成员变量其实是没有用的,如引用计数等。保留它们的目的是为了与vfs-node保持一致。这样在用ext-inode节点构造vfs-inode节点时,就不需要一个一个赋值,只需一次内存拷贝即可。
如果是非EXT格式的磁盘,就没有这么幸运了,所以mount非EXT磁盘会慢一些。
u  File
在 Linux 系统中打开的每个文件都都存在一个 file 对象。这个对象为特定用户提供打开的实例的信息。图 6 提供了文件对象的简化视图。在图中可以看到,path 结构提供到 dentry 和 vfsmount 的引用。为每个文件定义了一组文件操作,常见的文件操作包括 open、close、read、write 和 flush 等。接着定义一组标志和权限(包括组和所有者)。最后,为特定文件实例定义状态数据,比如文件的当前偏移量。

u  对象关系
我们已经查看了 VFS 层中的各种重要对象,现在我们通过一个图表展示它们之间的关系。到目前为止,我都是以一种自下而上的方式探索对象,现在我们采用自上而下方式,从用户透视图中考察对象。
在顶层是打开的 file 对象,它由进程的文件描述符列表引用。file 对象引用 dentry 对象,后者引用 inode。inode 和 dentry 对象都引用底层的 super_block 对象。可能有多个文件对象引用同一个 dentry(当两个用户共享同一个文件时)。注意,在图 7 中一个 dentry 对象还引用另一个 dentry 对象。在这里,目录引用文件,而文件反过来引用特定文件的 inode。


1.1.4 VFS内部架构
VFS 的内部架构由一个调度层(提供文件系统抽象)和许多缓存(用于改善文件系统操作的性能)组成。这个小节探索内部架构和主要对象之间的交互VFS 的内部架构由一个调度层(提供文件系统抽象)和许多缓存(用于改善文件系统操作的性能)组成。这个小节探索内部架构和主要对象之间的交互。

图10  vfs文件系统高级视图
在 VFS 中动态管理的两个主要对象是 dentry 和 inode 对象。缓存这两个对象,以改善访问底层文件系统的性能。当打开一个文件时,dentry 缓存将被表示目录级别(目录级别表示路径)的条目填充。此外,还为该对象创建一个表示文件的 inode。使用散列表创建 dentry 缓存,并且根据对象名分配缓存。dentry 缓存的条目从 dentry_cache slab 分配器分配,并且在缓存存在压力时使用最近不使用(least-recently-used,LRU)算法删除条目。您可以在 ./linux/fs/dcache.c 和 ./linux/include/linux/dcache.h 中找到与 dentry 缓存相关的函数。
为了实现更快的查找速度,inode 缓存被实现为两个列表和一个散列表。第一个列表定义当前使用的 inode;第二个列表定义未使用的 inode。正在使用的 inode 还储存在散列表中。从 inode_cache slab 分配器分配单个 inode 缓存对象。您可以在 ./linux/fs/inode.c 和 ./linux/include/fs.h 中找到与 inode 缓存相关的函数。在现在的实现中,dentry 缓存支配着 inode 缓存。如果存在一个 dentry 对象,那么 inode 缓存中也将存在一个 inode 对象。查找是在 dentry 缓存中执行的,这将导致 inode 缓存中出现一个对象。

3. 文件系统的挂载
挂载文件系统,目前有两种方法,一是通过 mount 来挂载,另一种方法是通过/etc/fstab文件来开机自动挂载;

1.1.5  通过mount 来挂载磁盘分区(或存储设备)
Ø  通过mount 来挂载磁盘分区(或存储设备)
挂载文件系统的命令格式
mount [-t 文件系统 ] [-o 选项] 设备 目录
注:
-t 通过这个参数,我们来指定文件系统的类型;如果忘记了文件系统,也可以在-t 后面加auto ;
-o 这个选项,主要选项有权限、用户、磁盘限额、语言编码等,但语言编码的选项,大多用于vfat和ntfs文件系统;
设备 指存储设备,比如/dev/hda1, /dev/sda1 ,cdrom 等...至于系统中有哪些存储设备,主要通过 fdisk -l 或者查看 /etc/fstab 或 dmesg ;一般的情况下光驱设备是/dev/cdrom ;软驱设备是/dev/fd0 ;硬盘及移动硬盘以 fdisk -l 的输出为准;
mount  /dev/cdrom
功能:mount 光驱/dev/cdrom,至于mount哪里,可以查看/etc/fstab
 
mount  /dev/cdrom  /mnt/cdrom
功能:mount 光驱/dev/cdrom,指定挂载位置为/mnt/cdrom
 
Ø  通过umount 来解挂磁盘分区(或存储设备)
Umount  挂载点
Umount 设备
Umount 设备 挂载点
 
1.1.6 通过/etc/fstab 来文件挂载磁盘分区(或存储设备)
文件各列含义:
设备名  
文件系统挂载点
文件系统类型
mount选项
文件系统是否需要备份(1需要;0不需要)
系统启动时,通过fsck磁盘检测工具来检查文件系统(1检查;0不需要)
Eg:


1.1.7 系统之mount流程分析
Mount  /dev/sdb  /mnt/alan 为例分析mount流程。
 
Ø  系统接卸“/mnt/alan”字符串 ,并从hash表中获取对应的dentry目录项,将其标识为DCACHE_MOUNTED;
Ø  内核创建该文件系统的superblock,并从/dev/sdb设备上读取所有superblock信息,初始化该对象(如果不是第一次挂载,则不必执行);
Ø  创建vfsmount对象(挂载点和设备之间的链接点),该vfsmount的mnt_root指针指向superblock对象的s_root根目录项。
 
以设备文件/mnt/alan/file.c为例,分析文件访问过程。
 
Ø  解析文件目录到/mnt/alan时,发现该目录项被标识为DCACHE_MOUNTED;
Ø  采用/mnt/alan计算HASH值去检索VFMOUNT hash table,找到对应的vfmount对象;
Ø  采用vfmount指向的mnt_root目录替代原来的dentry。
Ø  文件解析程序继续执行,得到ab.c。
五、文件系统相关的指令
Ø  mkfs格式化命令
mkfs  -t  文件系统  存储设备
Eg:mkfs  -t  msdos -c /dev/hda5  
 
Ø  fdisk 磁盘分区操作工具
n  -l 查看
n  -d 删除
n  -n 增加
n  -t 指定分区类型
 
Fdisk -l 查看分区情况

Ø  Mkswap 创建swap空间
 
Mkswap /dev/sda6  将/dev/sda6创建为swap分区
Mkswap  /tmp/swqp 创建swap文件
 
Ø  df调出目前已经挂载的设备及文件系统的磁盘使用情况


六、Linux系统安装时建立的默认目录结构
 Linux下的文件系统为树形结构,入口为/ 树形结构下的文件目录: 无论哪个版本的Linux系统,都有这些目录,这些目录应该是标准的。各个Linux发行版本会存在一些小小的差异,但总体来说,还是大体差不多。
1. / 文件系统的入口,最高一级目录;
2. /bin 基础系统所需要的命令位于此目录,是最小系统所需要的命令,如:ls, cp, mkdir等。这个目录中的文件都是可执行的,一般的用户都可以使用。
3.  /boot 包含Linux内核及系统引导程序所需要的文件,比如 vmlinuz initrd.img 文件都位于这个目录中。在一般情况下,GRUB或LILO系统引导管理器也位于这个目录;
4. /dev 设备文件存储目录。
5.  /etc 存放系统程序或者一般工具的配置文件。
6. /home 普通用户默认存放目录 Linux 是多用户环境,所以每一个用户都有一个只有自己可以访问的目录(当然管理员也可以访问)。它们以 /home/username 的方式存在。这个目录也保存一些应用对于这个用户的配置,比如 IRC, X 等。
7.  /lib 库文件存放目录这里包含了系统程序所需要的所有共享库文件,类似于 Windows 的共享库DLL 文件。
8.  /lost+found 在ext2或ext3文件系统中,当系统意外崩溃或机器意外关机,而产生一些文件碎片放在这里。当系统启动的过程中fsck工具会检查这里,并修复已经损坏的文件系统。 有时系统发生问题,有很多的文件被移到这个目录中,可能会用手工的方式来修复,或移到文件到原来的位置上。Linux 应该正确的关机。但有时你的系统也可能崩溃掉或突然断电使系统意外关机。那么启动的时候 fsck将会进行长时间的文件系统检查。Fsck 会检测并试图恢复所发现的不正确的文件。被恢复的文件会放置在这个目录中。所恢复的文件也许并不完整或并不合理,但毕竟提供了一些恢复数据的机会。
9. /media 即插即用型存储设备的挂载点自动在这个目录下创建,比如USB盘系统自动挂载后,会在这个目录下产生一个目录 ;CDROM/DVD自动挂载后,也会在这个目录中创建一个目录,类似cdrom 的目录。这个只有在最新的发行套件上才有. 
10.  /mnt /mnt 这个目录一般是用于存放挂载储存设备的挂载目录的,比如有cdrom 等目录。有时我们可以把让系统开机自动挂载文件系统,把挂载点放在这里也是可以的。比如光驱可以挂载到/mnt/cdrom 。
11.  /opt 表示的是可选择的意思,有些软件包也会被安装在这里,也就是自定义软件包,比如在Fedora Core 5.0中,OpenOffice就是安装在这里。有些我们自己编译的软件包,就可以安装在这个目录中;通过源码包安装的软件,可以通过 ./configure --prefix=/opt/,将软件安装到opt目录。这个目录包含所有默认系统安装之外的软件和添加的包。
12.  /proc 操作系统运行时,进程(正在运行中的程序)信息及内核信息(比如cpu、硬盘分区、内存信息等)存放在这里。/proc目录是伪装的文件系统proc的挂载目录,proc并不是真正的文件系统。
这是系统中极为特殊的一个目录,实际上任何分区上都不存在这个目录。它实际是个实时的、驻留在内存中的文件系统。
13. /root Linux超级权限用户root的家目录;
14. /sbin 大多是涉及系统管理的命令的存放,是超级权限用户root的可执行命令存放地,普通用户无权限执行这个目录下的命令;
15.  /tmp 临时文件目录,有时用户运行程序的时候,会产生临时文件。 /tmp就用来存放临时文件的。/var/tmp目录和这个目录相似。
许多程序在这里建立lock文件和存储临时数据。有些系统会在启动或关机时清空此目录。
16. /usr 这个是系统存放程序的目录,比如命令、帮助文件等。
l  当我们安装一个Linux发行版官方提供的软件包时,大多安装在这里。
其包括:
l  涉及字体目录/usr/share/fonts ;
l  帮助目录 /usr/share/man或/usr/share/doc;
l  普通用户可执行文件目录/usr/bin 或/usr/local/bin 或/usr/X11R6/bin;
l  超级权限用户root的可执行命令存放目录,比如 /usr/sbin 或/usr/X11R6/sbin或/usr/local/sbin 等;
l  还有程序的头文件存放目录/usr/include;
l  / /usr/local 这个目录一般是用来存放用户自编译安装软件的存放目录;一般是通过源码包安装的软件,如果没有特别指定安装目录的话,一般是安装在这个目录中。
l  这个目录下面有子目录。/usr/lib 和/lib 目录相似,是库文件的存储目录;
l  /usr/share 系统共用的东西存放地,比如 /usr/share/fonts 是字体目录;
l  /usr/src 是内核源码存放的目录,比如下面有内核源码目录,比如 linux 、linux-2.xxx.xx 目录等。
本站关键字:sunny90 web开发 数据库 移动开发 服务器 Nginx Mysql PHP
Copyright © sunny90版权所有 power by sunny90.com  
湘ICP备14012284号-1,粤公网安备 44030602000307号