linux最优秀的特点在于它是多用户多任务的环境,而且对于linux来讲一切皆文件,提到文件这个概念就免不了提文件相关的权限与属性的概念,那相关文件的属性记录在硬盘的哪个地方呢?这就需要了解linux的文件系统是如何记录文件,如何读取文件。
大家都知道硬盘作为存储介质,如果要使用硬盘存储数据需要对硬盘进行分区,格式化之后才可以存储数据。那为什么要对硬盘进行分区呢?因为我们必须要告诉操作系统:“这块硬盘可以访问的区域是有A柱面到B柱面”,只有这样,操作系统才能控制硬盘磁头去A~B范围内的柱面访问数据:如果没有告诉操作系统这个信息,那么操作系统就无法利用硬盘来进行数据访问,因为操作系统将无法知道它要去哪里读取数据。分区的要点:就是记录每一个分区的起始与结束柱面。
那么分区的起始与结束柱面的数据放在哪里呢?是放在主引导区(Master Boot Recorder,MBR)。事实上,MBR就是在一块硬盘的第0轨上,这也是计算机启动之后要去使用硬盘时必须读取的第一个区域。这个区域内记录了,这个区域内记录了硬盘里的所有分区信息,以及启动时可以写入引导程序的位置。当一个硬盘的MBR坏掉时,由于找不到分区数据,操作系统也就不知道该去哪个柱面读取数据。
在告知系统分区所在的起始与结束柱面之后,随后需要将分区格式化为“操作系统能够识别的文件系统”。因为每个操作系统能够识别的文件系统并不相同。例如,windows操作系统在默认状态下就无法识别linux文件系统,所以要针对操作系统来格式化分区。可以说,每一个分区就是一个文件系统,所以一个分区不可以有2个文件系统的,即将一个分区格式化的时候,不可能在格式化为ext3的同时也格式化为fat32格式。
无论是哪一种操作系统,总是需要存储数据。既然硬盘是用来存储数据的。当然,数据就必须写入硬盘。刚刚提到,硬盘的最小存储单位是扇区,而数据所存储的最小单位并不是扇区,因为用扇区来存储数据效率很低,因为每一个扇区只有512字节,而磁头是一个扇区一个扇区的读取,也就是说,如果文件有10mb,那么为了读这个文件,磁头必须要进行读取20480次,为了提高效率,就有了逻辑块(block)的概念.逻辑块是在对分区进行文件系统的格式化时所指定的“最小存储单位”。这个最小存储单位以扇区大小为基础(因为扇区是硬盘的最小存储单位),所以,块的大小为扇区的“2n”倍数,此时,磁头可以读取一块,假设在格式化的时候,指定块为4KB(即由连续的8个扇区构成一个块),那么同样一个10mb的文件,磁头要读取的次数则大幅降为2560次,这就大大提高了文件的读取效率。
不过,块单位的规划并不是越大越好,因为一个块最多能容纳一个文件,如果块规划为4KB,有一个文件大小为0.1KB,这个小文件就占用掉一个块的空间,也就是说,该快虽然可以容纳4KB的容量,然而由于文件只占用了0.1KB,所以实际剩下的3.9KB是不能再使用了。因此,在考虑块的规划时,需要同时考虑一下问题:
- 文件读取的效率
- 文件大小可能造成硬盘空间的浪费
因此,在规划磁盘时,需要考虑到主机的用途。如果文件比较小,那么块小一点,如果主机要存储大容量的文件,那么考虑到使用效率,当然块大一点会比较妥当。
在进行分区的时候,每个分区就是一个文件系统,而每个文件系统开始位置的那个块就称为超级快(superblock).超级块的作用是用来存储文件系统的大小,空的和填满的块以及它们各自的总数和其他诸如此类的信息。这也就是说,要使用这一个分区(或文件系统)来进行数据的访问时,第一个要经过的就是超级块,所以超级块坏了,这个磁盘也就没有什么用了。
linux的文件系统:
在linux系统中,每个文件不仅有内容数据,还包括文件的各种属性,例如,所属用户组,所属用户,能否执行,文件建立时间,文件特殊属性等等。由于linux是一个多用户,多任务的操作系统,为了保护每个用户所拥有数据的隐秘性,具有多样化的文件属性是在所难免的。在标准的ext2文件系统中,将每个文件的内容分为两个部分来存储,一个是文件的属性,另一个则是文件的内容。考虑到这两方面的因素,ext2规划出inode与块来分别存储文件的属性(放在inode)与文件的内容(放置在块区中)。要将一个分区格式化成ext2时,就必须要指定inode与块的大小才行,也就是说,当分区格式化为ext2的文件系统时,它一定会有inode表块区域这连个区域。
块已经在前面说过了,它是数据存储的最小单位,inode是什么呢?块是记录文件内容数据的区域,inode则是记录该文件的属性,以及文件内容放置在哪一块内的信息。inode除了记录文件的属性外,同时还必须具有指针的功能,即指向文件内容放置的块之中,让操作系统可以正确获取文件的内容。下面几个是inode记录的信息:
- 该文件的拥有者与用户组(owner/group);
- 该文件的访问模式(read/write/excute);
- 该文件的类型(type);
- 该文件建立或状态改变的时间(ctime),最近一次的读取时间(atime),最近修改的时间(mtime)
- 该文件建立或状态改变的时间(ctime),最近一次的读取时间(atime),最近修改的时间(mtime)
- 该文件的大小
- 定义文件属性的标志(flag),如SetUID
- 该文件真正内容的指针。
一个块分区在ext2下会被格式化为inode表与块区域两个部分,例如读取/etc/crontab的流程为:
- 操作系统根据目录(/)的相关数据可获取/etc目录所在的inode,并读取/etc/这个目录的所有相关属性
- 根据/etc的inode的数据,可以获取/etc/目录下所有文件的关联数据是放置在哪一块中,并前往该块读取文件的关联性内容。
- 由上一个步骤的块中,可以知道crontab文件的inode所在地,并前往该inode
- 由上一个步骤的inode中,可以获取crontab文件的所有属性,并且前往有inode所指向的块区域,顺利获取crontab的文件内容。
查看根目录所记载的所有文件关联性数据:
注意,上面的 . 与 . . 都是连接到inode号码为2的那个inode
也就是说,/ 与其上层目录 . .都是指向一同一个inode号,两者是相同的。
在根目录所记载的文件关联性(在块内)得到/etc/inode号为3145729
查看/etc/内的文件关联性的数据:
此时就能对/etc/crontab找到关联性。
由此可知,目录的最大功能就是在提供文件的关联性,在关联性中,最主要的就是“文件名与inode的对应数据”。
另外关于ext2文件系统相关知识:
- ext2与ext3文件在建立时就已经设置好固定的inode数与块数目了。
- 格式linux的ext2文件系统,可以使用mke2fs程序来执行
- ext2允许的块的大小为1024,2048,4096字节
- 一个分区(文件系统)所能容纳的最大文件数与inode数量有关,因为一个文件至少占用一个inode
- 目录下的文件数如果太多,导致一个块无法容纳所有的关联数据,linux会给予该目录多个块,来继续记录关联数据。
- 通常inode数量设置为“分区的容量”除以“一个inode预计想要控制的容量”。
- 因为一个inode只记录一个文件属性,所以inode数量比块多是没有意义的。
- 块越小,inode数量越多,则可利用的空间越多,但大文件写入的效率较差;这种情况适合文件比较多但文件小的系统。
如果想知道某个文件系统的信息,可以使用dumpe2fs命令来读取
因为数据很多,所以略去了一些信息。在group0之前都是超级块的内容,记录了inode块的总数,group0之后的,则是说明各个位图及inode表与块区域等。通过这些记录,可以很轻松的知道哪些inode没有用,哪些块还可以记录,这样,在新增,建立文件与目录时,系统就根据这些记录将数据分别写入尚未使用的inode与块区域。不过,要注意的是,当我们新增一文件(目录)时:
- 根据inode位图/块位图的信息,找到尚未使用的inode与块,进而将文件的属性与数据分别记入inode与块。
- 将刚刚使用的inode与块的号码(number)告知超级块,inode位图,块位图等,让这些元数据更新信息
一般来说,我们将inode表与块的区域成为数据存放区域,其他的诸如超级块,块位图与inode位图等记录称为元数据(metadata)。
但是有没有考虑过这样的情形,文件在写入硬盘时,很可能因为未知原因导致系统中断(如突然停电,系统核心发生错误等),数据只记录到操作1,而操作2尚未进行,就会发生元数据与数据存放区不一致的情况。在早期的ext2文件系统中,如果发生这个问题,系统在重新启动的时候,就会通过超级块中记录的有效位与文件系统状态等,判断是否强制进行数据一致性检查。使用e2fsck程序来进行检查。不过这样的检查很费时,因为要针对元数据区域与实际数据存储区来进行比较,要搜索整个分区,系统会很忙。而且在对internet提供服务的服务器主机上,这样的检查会造成主机复原时间更长,非常麻烦,这也是为什么出现日志文件系统产生的原因之一。
在ext2的文件系统中,要写入文件时,会在数据存放区与元数据区域分别记录数据,当这两个动作无法一次完成是,就会造成不一致,此时操作系统就触发文件系统一致性检查,这样很费时,如果在文件系统中规划出一个块,专门记录写入或修改文件时的步骤,就可以简化一致性检查的步骤了,也就是说:
- 当系统写入一个文件的时候,先在日志记录块中记录:某个文件准备要写入磁盘了
- 开始写入文件的权限与数据
- 开始更新元数据的数据
- 完成数据与元数据的更新后,在日志记录块中完成该文件的记录
当数据记录过程中发生了问题,系统只要去检查日志记录块,就可以知道是哪个文件的问题,并针对该问题做一致性检查即可,而不必针对整块文件系统去检查,这样就可以快速修复文件系统了。这就是日志文件最基础的功能。ext2文件也可以通过ext3实现日志功能。
经过上述描述,我们知道了整个ext2/ext3的数据访问时通过日志与元数据以及数据存放区记录的, 为了加快真个linux系统的访问速度,linux通常采取异步处理的方式,当系统读取了某个文件,则该文件所在的块数据会加载到内存中,所以该磁盘块就会存放在主存储器的缓冲区中,如果这些块的数据被修改之后会存放在缓冲区中,所以我们把内存块中被修改的数据称之为“脏数据”,此时物理磁盘上的数据块还没有被修改,所以这些脏数据迟早要写回到磁盘上面,保证缓存和磁盘上数据的一致性。所以数据在内存中被修改后不会立即写入物理磁盘上面,因为内存的运行速度要比硬盘快很多,如果文件被连续访问,每次都要从硬盘读取,这样会降低linux的运行速度,所以才会使用异步方式处理数据。
前面提到的都是关于文件系统的概念,要能够使用linux,必须要“载入(mount)”linux系统,刚刚提到,目录可以记录文件名与inode的相关信息,并且与文件系统能够产生对应的入口点,因此,我们称那个入口点目录为“载入点(mount point)”.
linux支持的其他文件系统
虽然linux的标准文件系统是ext2,而且还增加了日志功能的ext3,事实上,linux还支持很多文件格式。近几年推出了集中速度很快的日志文件系统,包括SGI的XFS文件系统、可以适用于更小型文件的reiserfs文件系统,以及Windows的FAT文件系统等,都能被linux支持,常见的文件系统有:
- ext2/ext3/ext4/xfs/btrfs文件系统
磁盘的分区、格式化、检验与载入
对于系统管理员(root)而言,磁盘管理是相当重要的,如果服务器在系统里新增硬盘,需要做如下一些事情:
- 对磁盘分区,以建立可用的分区
- 对分区进行格式化,以建立系统可用的文件系统;
- 可对刚建立好的文件系统进行检验;
- 在linux系统上需要建立载入点(即目录),并将它载入。
在上述的过程中,还有很多需要考虑的事项,例如,分区大小如何规划,是否加入日志功能?,inode与块数量应该如何规划等。但是这些问题的决定,都需要根据主机用途来考虑。
那我们来学习如何为linux主机进行分区吧:
分区:fdisk
fdisk [-l] 设备名称
参数:
-l:输出后面接的设备所有的分区内容。若仅有fdisk –l时,将会把整个系统内能够搜索到的设备分区均列出来了,可以看出第二块硬盘/dev/sdb还没有分区呢。
接下来我们就对/dev/sdb第二块硬盘分区吧,执行fdisk /dev/sdb,输入“m”可以获取如图所示的命令以及相关说明
接着输入p ,可以输出当前磁盘的状态
我们创建一个新的分区吧:输入“n”
n:新增一个分区,如果已经有扩展分区,系统会问,要新增的是主分区还是逻辑分区,如果还没有扩展分区,系统就会问要新增主分区还是扩展分区。除此之外,如果已经用完4个主分区+扩展分区,那么就仅有逻辑分区可以选择。如果选择主分区,请按p,否则请按e (扩展分区)或 1(逻辑分区);
p:由于选择为主分区,所以就会按下p
1-4:主分区只允许有4个,所以这里请按 1
w:存储离开。
最后输入p就可以看到刚刚我们创建的5G的主分区了。
接着在建立一个扩展分区:
建立一个逻辑分区,编号一定是从5开始的
现在可以查看系统上的分区情况了
通过这个例子可以清晰的看到,第一个逻辑分区是在5号,在fdisk完成之后,请记住使用mke2f格式化,如果操作有误,那么可以按”q”离开了。
现在对磁盘进行分区了,就可以对磁盘进行格式化了:
mke2fs [-bicLj] 设备名称
参数:
-b:可以设置每个块的大小,当前支持1024、2048、4096字节3种。
-i:给一个inode多少容量
-c:检查磁盘错误,仅执行一次 –c 时,会进行快速读取测试。
-L:可以指定卷标(Label)
-j:本来mke2fs是ext2,加上 -j后,会主动加入日志而成为ext3
举例说明:
将/dev/sdb5格式化为ext3,且名称为logical。