Linux ext2文件系统

硬盘

  在一个硬盘在Linux下,被虚拟成文件。在/dev目录下,实体机是/dev/sd[a-p],虚拟机下是/dev/vd[a-d]。总体来说第一个硬盘被虚拟的文件总体来为/dev/sd[a-p][1-128]。(不过我的虚拟机下的,/dev目录下的文件是/dev/sda)。
  硬盘是由分区和磁臂构成。每次写入数据的时候,磁臂旋转到相应的磁道上,对其读写数据。
  何为分区呢?列如我的硬盘被抽象成了/dev/sda, /dev/sda1 /dev/sda2 这俩个就是指分区,代表sda硬盘的分区1和分区2。

文件系统

  我们可以把一个硬盘划分为几个分区,传统的一个分区对于一个文件系统。现代可以RAID技术把多个分区合成为一个文件系统。我的系统下,一个分区一个文件系统。不过在书上看到有其他技术可以把多个分区划为一个文件系统或者多个文件系统一个分区。
  文件系统大致把所有文件分为俩部分,一部分为 block 它主要存了数据,一部分为inode节点数组,每个inode节点存放了对应文件的重要信息(struct stat 中保存了大量的inode节点中的数据)。因为inode节点记录了该文件的所有块的索引,所以linux下的文件系统I/O时很高效,它是索引式文件系统,在I/O时一下就可以得到所有的块号,方便硬盘I/O。
  对于实际的数据就被存在了block中。block数还划分为数据块和目录块。我们通常遍历的目录是目录块,目录块就只保存了其下所有目录项,每个目录项都保存着一个相应的文件名和inode节点号。(对此我们可以通过struct dirent看出)
  另外还有一个superblock,它记录了文件系统的信息,包括 inode 与 block 的总量、使用量、剩余量等。

           struct dirent {
               ino_t          d_ino;       /* inode号 */
               off_t          d_off;       /* 下一个目录项的偏移量*/
               unsigned short d_reclen;    /* length of this record */
               unsigned char  d_type;      /*文件类型*/
               char           d_name[256]; /*文件名*/
           };
实际上inode节点中还有数据块的标号,在以下stat结构体中没有表现出来。
           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode节点号 */
               mode_t    st_mode;    /* 权限 */
               nlink_t   st_nlink;   /* 硬链接的链接数 */
               uid_t     st_uid;     /* 用户id该id在口令文件中对应着相应的用户 */
               gid_t     st_gid;     /*用户组id*/
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /*文件总大小*/
               blksize_t st_blksize; /* 该文件对于I/O时最合适的大小 */
               blkcnt_t  st_blocks;  /* 被分配的block数目 */
               time_t    st_atime;   /*访问时间*/
               time_t    st_mtime;   /*最后一次修改文件内容的时间*/
               time_t    st_ctime;   /*最后一次修改文件状态的时间,即访问inode节点的时间*/
           };

ext2文件系统

这里写图片描述

BootSector

  它是引导电脑启动的扇区,由于这个属性,所以Linux下可以以不同的分级来启动。

BlockGroup

  以下是块分组的组成内容

1.DataBlock

这里写图片描述
对此当我们,设置不同的block大小时,对于文件也有不同的限制。对此外还有几点限制:
1.原则上, block的大小与数量在格式化后就不能够再改变了。(重新格式化可以)
2.每个块中只保存一个文件的数据
3.如果文件大小大于该块,该文件就占据多个块,但是如果一个文件小于该块,该快剩余的容量就不能被其他文件所使用了,所以对于小文件,十分浪费容量。即使该文件几十字节,也为它分陪一个块。
4.块大小设置大了,我们如果有大量小文件时,浪费硬盘容量,如果设置太小了,一个文件有多个数据块,I/O时,磁臂会浪费大量时间在寻找磁臂上,浪费大量时间导致I/O效率降低。

2.InodeTable

  它就是一个Inode节点数组,Inode节点存放的数据基本在stat结构体中了,在上面已经写过了。
  对于块号怎么在inode节点存储是这样的,一个inode节点有12个直接块,1个间接块,1个双简介块,1个三间接块字段,每个字段大小4字节。
  直接块的索引就是指向了一个直接保存数据的块。间接块指向了一个块,该块存放了直接块的索引,剩下的间接块类似。
  对于inode节点还有以下几点认识:

  1. 每个inode节点固定为128字节(ext4 256)
  2. 一个文件一个inode
  3. 一个文件系统能创建多少文件与inode节点数量有关
  4. inode数组的数量在文件系统格式化的时候就确定了
  5. 程序在读取文件的时候,都是先用fd文件描述符对应的struct file 结构体的指针,找到一个文件对象表,该文件对象表中保存了,文件的偏移量和inode节点号,根据inode节点号找到inode节点,然后用该进程的euid/egid和inode节点中的权限做对比,如果符合才能读取。

3.Superblock

Superblock主要保存了文件系统的相关信息。而每个BlockGroup中都有一个该文件系统的备份也叫Superblock。对于它记录的信息主要有:

1.该文件系统 block 与 inode总量
2.未使用与已使用的inode/block数量
3.block和inode的设置的大小(block 1/2/4K inode 128/256字节)
4.文件系统的挂载时间、最近一次读写时间、挂载时间。
5.valid bit 字段,0 表已被挂载,1表未被挂载
对于挂载,任何一个文件系统未被挂载到某个目录下是不能被访问的,只有被挂载后才能访问。

4.Filesystem Description

这个区段是来描述每个block group的起始块号与终止块号。还有该block group各个数据成员在那个block号之间。

5.block bitmap

从名字上可以看出来这个东西是一个位图。它记录了该block group块数组)中所有块的使用情况,每一位标记了该块是被使用的还是未被使用的。当我们在一个目录下创建一个文件的时候,系统就会在该文件系统下查找block bitmap,来找到相应未被使用的block分配给新文件

6 inode bitmap

这个和block bitmap相似,它也是一个位图,记录inode节点的使用情况的。

对文件系统的一些指令

blkid

这个指令可以显示当前系统下所有被格式化过的设备文件名字。
这里写图片描述

dumpe2fs

dumpe2fs 选项 相应设备文件名 ,它可以显示出相应硬盘文件的详细信息
-b 显示坏轨
-h 列出Super block 信息

这里写图片描述
这里写图片描述

文件系统与目录树

  目录也是一个文件,不外乎它的数据分俩部分存储,权限与属性信息存在inode节点中,数据存在block表中的相应block中。
  我们对访问一个目录的时候,首先系统会查找该文件系统的挂载点。就是上面超级块哪里显示的Last mounted on 字段,然后访问挂载点inode节点,找到相应的block。一个目录的block,它里面只是保存着其下所有目录项的名字和对应的inode节点,然后根据路径名一直如上面步骤访问,找到相应的数据块,进行I/O。当然一路上都是会跟相应inode节点的权限进行对比的,如果权限不允许会报错Permission denied。

文件系统的日志功能

  就上面超级块中的Journal字段,日志机制是为了防止断电导致的数据不一致问题而衍生的。如果要创建一个目录项的时,会做如下几点:

  1.我们会首先检查我们是否有对该父目录有w和x权限。
  2.如果有接下来会访问inodemap和blockmap,找到空闲的inode节点和空闲的块,然后把文件的属性信息写到inode中,数据写到block中。
  3.完成写入后更新Superblock/inodemap/blockmap中的信息。
  

  那如果在第二步完成后突然断电了,这时候这个文件的inode节点和数据都是写完了,所以在该目录下是有该文件的,但是却没有在Inodemap/blockmap中更新。这样的话,可能该inode节点和数据块又再次分配,造成数据不一致问题。这时候只要检查日志数据块就可以修复了。

挂载

  把文件系统挂载到某个目录下这个动作称为挂载,如果没有把文件系统挂载某个目录下我们是不能对它进行访问的。被挂载的目录我们称为挂载点,挂载点是访问文件系统的起始目录.
  对了很重要的一点就是不一定,一定要把一个文件系统挂载到根目录下,也可以挂载到其他目录下。

I/O

对于硬盘I/O时,由于硬盘I/O速度太慢,所以Linux下采用了异步(asyn)处理的方式,其实就是把硬盘上的文件读取到内存中,要写回硬盘时,并不会立刻写回,系统会不时的将被修改的内容写回硬盘。但是我们可以使用sync指令强迫系统让系统将修改的数据写好硬盘并更新Superblock、blockbitmap。

virtual filesystem switch

这个是内核的一个模块,它向用户抽象了所以的文件系统,便于用户访问文件时不必关系该文件是什么文件系统。

查看硬盘情况的指令

df

df [-hTi] 参数
-h: 以人类的方式显示,G/M/K的方式显示出来
-T: 显示的时候加上每个文件系统的类型
-i:显示出inode节点的使用情况
-a: 显示出所有的文件系统,包括特殊文件系统和swap
  df是用来查看文件系统的整体硬盘使用量。当不带参数时会列出所有文件系统的情况,当根某个目录或文件,会列出该文件所在的文件系统的情况。

du查询目标所

du [-ahs] 文件/目录
  du用来统计目标目录项的数据块占用的字节数,如果不加-a选项只显示目标目录下所有子目录的字节数,而加上-a选项连文件的字节数也会被显示出来。
  -s选项只显示目标的字节数,不显示子目录的结果。
  -S选项,因为默认du会统计目标目录下的字节数和目标目录下所有子目录,目标目录下的所有文件都会被统计一次。如果只想显示目标目录的字节数,只需加上-S选项即可。
  默认单位是KB。

猜你喜欢

转载自blog.csdn.net/sdoyuxuan/article/details/78333321
今日推荐