为什么磁盘分区完毕后要进行格式化?
因为每种操作系统所设置的文件属性/权限并不相同,不格式化,操作系统无法识别这些数据,因此要将分区格式化,成为操作系统能利用的文件系统格式。
每种操作系统使用的文件系统并不相同,Linux的正规文件系统为Ext2(Linux second extended file system,Ext2fs)。在默认情况下,Windows操作系统是不会认识Linux的Ext2的。
我们称呼一个可被挂载的数据为一个文件系统而不是一个分区。
Linux文件系统将文件权限和属性和文件实际数据分别放置在两个不同的块中。文件权限和属性放置在inode中,文件实际数据放置在data block中。另外还有一个超级块(super block)会记录每个文件系统的整体信息,如inode和block总量,已使用量,未使用量等。每个inode和block都有编号。
Super block:记录文件系统的整体信息,包括inode和block的总量,使用量,剩余量,以及文件系统的格式与相关信息。
inode:记录文件的属性,一个文件占用一个inode,并记录此文件的数据所在的block号码
block:实际记录文件的内容,若文件太大,会占用多个block
文件系统先格式化出inode和block块,假设一个文件的权限和属性数据放置在inode4号,inode4号记录了该文件的实际数据放置在2,7,13,15这4个编号的block中,操作系统就能据此找到这4个block并读取内容。
这种数据访问方法我们称为索引式文件系统。还有其他形式的文件系统如U盘,U盘使用的文件系统是FAT格式,这种格式的文件系统没有inode,所以FAT无法将这个文件所有的block在一开始就读取出来。每个block号码都记录在前一个block当中,它的读取方式如图所示。
假如我们把文件的数据依次写入1,7,4,15号这4个block号码中,但FAT格式的文件系统无法一口气知道这四个block号码,它需要先访问第一个block才知道下一个block在哪里。如果一个文件的block分散的太厉害,盘片转一圈无法读完,就需要多转好几圈才能读取到该文件内容。
磁盘碎片整理的原因就是文件的block分散的太厉害了,文件读取的性能将会变得很差。我们可以通过磁盘碎片整理将同一个文件所属的block汇合在一起,这样读取数据比较容易。
FAT格式的文件系统由于读取文件的机制会经常需要碎片整理,而Ext2文件系统由于是索引式文件系统,基本不太需要碎片整理。
文件系统一开始就将inode和block规划好了,除非重新格式化或者利用resize2fs等命令更改文件系统大小,否则inode和block固定后就不再变动。
当一个文件系统太大,其拥有的inode和block数量也很大,不容易管理,因此将文件系统格式化的时候分成多个块组,每个块组都有独立的super block,inode和block。
每个文件系统最前面有个启动扇区,可以安装引导装载程序,这样不用覆盖整块硬盘唯一的MBR,还能够制造出多重引导的环境。
Ext2文件系统示意图:
用来放置文件内容,在Ext2文件系统中所支持的block大小仅有1KB,2KB,4KB这三种。在格式化时block的大小就已经固定了,而且每个block都有编号,以方便inode记录。而block大小的区别会导致该文件系统能支持的最大磁盘容量与最大单一文件容量并不相同。
block大小 | 1KB | 2KB | 4KB |
---|---|---|---|
最大单一文件限制 | 16GB | 256GB | 2TB |
最大文件系统总容量 | 2TB | 8TB | 16TB |
注:虽然Ext2已经能够支持大于2GB以上的单一文件容量,但某些应用程序依然使用旧的限制,只能够支持小于2GB的文件。
假设你的Ext2文件系统使用4KB的block,而该文件系统中有10000个小文件,每个文件大小都是50Bytes,此时你的磁盘浪费了多少容量?
(4×1024-50)×10000÷1024÷1024=38.59MB
不到1MB的总文件容量却浪费了将近40MB的磁盘空间,而这种小文件越多,磁盘空间浪费越大。虽然大的block会造成严重的磁盘空间浪费,但如果block较小而我们存的文件普遍较大的话,就会使用很多block来记录数据,inode也要记录更多的block号码,造成文件读取性能不良。
所以在格式化文件系统之前,应该先想好该文件系统所存文件普遍是大型文件还是小型文件。
每个inode大小固定为128Bytes
每个文件都仅会占用1个inode
文件系统能够创建的文件数量与inode数量有关,无剩余inode时就无法创建文件
系统读取文件时需要先找到inode并分析inode所记录的权限和用户名是否符合,符合才能够开始读取block的内容
假设有个400MB的文件,且文件系统的block大小为4KB,要记录下这个文件需要400×1024÷4=102400个block,那么inode就得记录102400个block号码,一个block号码要花掉4bytes,记下102400个号码要花掉102400×4bytes,而一个inode的大小仅有127bytes,空间明显不够用。
于是系统将inode记录block号码的区域定义为12个直接,一个间接,一个双间接和一个三间接记录。
inode结构示意图
如图所示,一个inode中有12个直接记录block号码,间接表示借用1个block来记录block号码,而间接中存储它借用的block号码。双间接表示再借用1个block来记录block号码。这样一来,一个inode能记录多少号码呢?我们以较小的1KB的block来说明。
12个直接指向总共可以记录12条记录。
1个间接指向:1个block,1KB=1024bytes,记录1个号码需要4bytes,那么可以记录1024÷4=256个block号码。
1个双间接指向:第一层block记录256个block号码,第二层block有256个,每个能指向256个block,那么就是可以记录256×256个block号码。
1个三间接指向:第一层block记录256个号码,第二层block有256个,每个能指向256个block,第三层block有256×256个,每个能指向265个号码,那么就是可以记录256×256×256个号码。
所以一个inode总共可以指向12+256+256×256+256×256×256=16843020个block,而每个block为1KB大小,所以单个文件存储的最大容量应该是16843020÷1024÷1024≈16.06GB,这个计算结果恰好和1KB时最大单一文件限制大小是一样的。但这个计算方法不能用在2KB和4KB的block大小的计算中,因为大于2KB的block将会受到Ext2文件系统本身的限制。
superblock是记录整个文件系统相关信息的地方,没有superblock就没有文件系统了。
block和inode的总量
未使用和已使用的inode及block数量
block和inode的大小(block为1K,2K,4K,inode为128bytes)
文件系统的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统相关信息
一个validbit数值,若此文件系统已被挂载,则valid bit为0,若未被挂载,则valid bit为1
如果superblock死掉了,文件系统可能就需要花费很多时间去挽救。一般来说superblock的大小为1024bytes。此外,每个block group可能都含有一个superblock作为第一个block group内superblock的备份,这样方便进行superblock的救援。
记录了每个block group开始与结束的block号码,以及说明每个区段(superblock,bitmap,inodemap,data block)分别介于哪两个block号码之间。
记录了哪些block是空的,这样文件系统就能很快找到空的block来处理数据。
记录了哪些inode是空的,这样文件系统就能很快找到空的inode来处理数据。
注:这一小节跟鸟哥的Linux私房菜中不一样,他的文件系统默认为Ext2的,可以用dumpe2fs命令查看,但我装的是CentOS 7,默认的文件系统是XFS,要用xfs_info命令查看。
首先我们了解以下df命令
df [-lhT] [文件名]
-l:–local,仅显示本地文件系统
-h:–human-readable,以人们易读的KB,MB,GB形式显示
-T:–print-type,显示文件系统类型
示例1:找出我的根目录磁盘文件名,并查看文件系统相关信息。
这边为了显示文件系统类型,可以用df -lhT命令如图所示
如图所示,在我的CentOS 7中,文件系统类型只有xfs和tmpfs和devtmpfs,不是Ext2。
df命令可以调出目前挂载的设备,上图显示挂载在根目录上的文件系统名为/dev/mapper/centos-root。
输入xfs_info /dev/mapper/centos-root
为了方便观看,我让结果显示了行号
如图所示
第1行的isize指的是inode的大小,每个大小是512bytes。agcount指的是block group的个数为4个,每个block group中有2424320个block。
第2行的sectsz是每个扇区大小512bytes
第4行中bsize说的是block的大小为4K,文件系统内共有9697280个block,这个数值正好是第1行中2424320×4。
第7行的意思是指这个登录区在这个文件系统内,不是外部设备。且占用了4735个block即4735×4K≈18.5MB的容量。
当我们在Linux下的ext2文件系统中新建一个目录时,ext2会分配一个inode与至少一个block给该目录。其中inode记录目录的权限及属性,并记录存储实际数据的block号码,而block记录该目录下文件名和该文件名占用的inode号码。
示例1:查看root家目录内文件所占用的inode号码
当我们在linux下的ext2新建一个一般文件时,ext2会分配一个inode与相对于该文件大小的block数量给该文件。假如我的一个block大小为4K,而我要新建一个100K的文件,那么Linux将分配1个inode和25个block给该文件,由于inode仅有12个直接指向,所以还要多分配1个block用于间接指向。
inode本身并不记录文件名,文件名被记录在目录的block中,当我们读取一个文件时,先从根目录开始读起,在根目录的block中找到下级目录的目录名和inode号码,然后读取下级目录的inode号码找到下级目录的block,循环往复,直至在一级目录的block中找到该文件名和文件的inode号码,然后通过访问文件的inode号码找到真正存储文件数据的block号码,访问block读取数据。
例如,我想读取/etc/passwd这个文件
当一个文件系统规划的很大时,由于磁盘上的数据是一直在变动的,所以整个文件系统上面的文件block都是离散的,不会是连续的,如果block真的分得很散,就发生了文件数据离散的问题,造成读取效率低下。
将文件全部复制出来,然后将文件系统重新格式化,能够有效地解决这个问题。
如果文件系统太大,当一个文件的block分别位于文件系统的最前面和最后面,读取该文件时会造成机械手臂移动幅度过大,数据读取性能低下,因此文件系统不是规划得越大越好,要视用途而定。
当我们新建一个文件时,文件系统的行为是:
注:因为inode bitmap和block bitmap中记录了未使用的inode和block号码,而superblock中记录了文件系统未使用和已使用的inode和block数量,最后一次写入数据的时间等信息。新建文件后这些数据都会产生变化,所以最后一步是更新inode bitmap,block bitmap和superblock。
一般来说,我们将inode table和block table称为数据存放区域,inode bitmap、block bitmap和super block等区段被称为meta data(中间数据),因为super block,inode bitmap和block bitmap是经常变动的,每次添加、删除、编辑时都会影响到这三个部分的数据,因此被称为中间数据。
如果新建文件的时候,突然断电,内核发生错误等影响导致新建操作中断,容易出现将文件数据写入了却没有更新inode bitmap和block bitmap数据。同步操作没有完成,就容易造成数据不一致的状态。
在早期的Ext2文件系统中,如果发生这种问题,文件系统的应对措施时,在系统重新启动的时候,通过super block中记录的valid bit(是否有挂载)与文件系统的state(clean与否)等状态来确定是否需要强制进行数据一致性检查。如果需要则以e2fsck这支程序来进行。但这样的检查很费时,需要对比整个文件系统,尤其是文件系统很大,文件数量很多的情况下。
Ext3是ext2文件系统的升级版,可向下兼容ext2文件系统。它在文件系统中规划出一个块,专门记录写入和修订文件时的步骤。
当数据不一致状态出现的时候,系统只需要去检查日志记录块,就知道是哪个文件的哪个步骤发生了问题,针对该问题做一致性检查即可,不必正对整个文件系统检查,达到快速修复文件系统的作用。
所有数据都得加载到内存后CPU才能对该数据做处理。如果你经常要编辑一个很大的文件,在编辑过程中又频繁地将文件写入磁盘中,由于磁盘写入的速度比内存慢很多,这是很没效率的做法。
我们的Linux是通过异步处理(asynchronously)来解决这个问题的。
当系统加载一个文件到内存时,如果这个文件没被改动过,标记为clean。如果被改动过了,该内存中的数据被设置为dirty,此时所有操作还在内存中进行,没有写入到磁盘中,系统会不定时的将内存中设置为dirty的数据写回磁盘,以保持磁盘与内存数据的一致性。
系统将常用到的文件数据放在主存储器的缓冲区,以加速这个文件的读写。因此Linux的物理内存最后都会被用光,这是正常的情况,可以加速系统性能。
用户可以手动使用sync指令(将数据同步写入到磁盘)来强迫内存中设置为dirty的数据写回到磁盘中。
正常关机时,关机命令会主动调用sync命令将内存中的数据写入到磁盘中。
若非正常关机(断电,死机或其他不明原因),由于数据尚未写回磁盘内,因此重新启动后可能会花很多时间进行磁盘检验,甚至可能导致文件系统损坏。
每个文件系统都有独立的inode,block,super block等信息,文件系统要能够链接到目录树才能被我们使用。将文件系统与目录树结合的操作就是挂载。挂载点一定是目录,该目录为进入该文件系统的入口。
如图所示,我的CentOS 7上一共有7个文件系统,他们都被挂载在不同的目录下。
而这几个文件系统挂载点目录的inode号码如图所示
如图所示,我们发现XFS文件系统的挂载点目录的inode号码都是一样的,都是64。
文件系统的某个inode只会对应到一个文件内容,我们可以从这点出发来证明/、/.和/..是相同的文件。
如图所示,这三个文件的挂载点均为/,因此在同一个文件系统内,而他们的inode的都是64,因此这三个文件名都指向同一个inode号码,内容当然也完全一样。
Linux也支持其他文件系统,如SGI的XFS文件系统(就是目前CentOS 7的默认文件系统),可以适用于更小型文件的Reiserfs文件系统,Windows的FAT文件系统等,都能被Linux支持。
查看下面的目录可以知道你的Linux支持的文件系统有哪些,如图所示,我的CentOS 7支持下面这些文件系统。
内核当前支持的文件系统类型有
整个Linux系统都是通过一个名为Virtual Filesystem Switch(虚拟文件系统,VFS)的内核功能去读取这些文件系统的。Linux认识的文件系统都是VFS在进行管理,我们读取文件时并不需要知道文件系统是什么,不需要特别制定用什么文件系统的模块读取,VFS会主动帮我们识别文件系统,做好读取工作。
VFS文件系统示意图
用df和du指令可以查询文件系统的总容量和每个目录所占用的容量。
我们知道,磁盘的整体数据是在super block中记载的,而目录的容量是在inode中记载的。
df [-ahikHTm] 文件名或目录名
-a:列出所有的文件系统,包括系统特有的/proc的文件系统
-h:以人们较易阅读的KB,MB,GB等容量单位自行显示文件系统
-i:不用硬盘容量,以inode的数量来显示容量
-k:以KB为容量单位显示各文件系统
-H:以M=1000KB来取代M=1024KB的进位方式
-T:连同该分区的文件系统名称一起列出。
-m:以MB为容量单位显示各文件系统
示例1:分别用df和df -a列出所有的文件系统,对比结果差别
如图所示,我们发现df列出的仅是一部分文件系统,而df -a的结果中容量数据都为0的特殊内存内的文件系统在df的结果中并没有列出。这些特殊文件系统因为都是在内存里的,因此没有占用磁盘空间。
示例2:将系统内所有特殊文件格式和名称都列出来,并且以KB,MB,GB形式自行显示容量。
如图所示,根目录下挂载的文件系统类型是XFS的,CentOS 7开始linux的默认文件系统就是XFS。
示例3:将/etc目录下的可用容量以易读的容量格式显示
如图所示,当df指令后加上文件或目录作为参数时,指令会查出该目录或文件所在的文件系统并列出其容量相关数值,这样我们就知道/etc目录下还有36G的磁盘容量可供使用。
示例4:将各个分区的文件系统可用的inode数量列出
注:当Use%这一栏在90%以上时,要特别注意,免得容量不足造成系统问题。
df读取的数据是针对整个文件系统的,是从super block中读取的,因此读取速度很快,要特别注意根目录的可用容量,因为所有目录都是从根目录衍生出来的,如果根目录可用容量为0%,linux就会出问题。
特别说一下/dev/shm这个目录,其实是内存虚拟出来的磁盘空间,在该目录下建立任何文件访问速度都是非常快速的,但是因为是在内存中,建立的东西在下次登录时就会消失。
du [-asShkm] 档案或目录名称
-a:列出所有档案和目录容量。 因为不加参数的情况下仅统计当前目录下的目录和档案容量。
-s:仅列出总量,不列出每个目录占用容量
-h:以人们易读的容量格式显示(KB,MB,GB)
-S:不包括子目录下的统计,与-s有点区别
-k:以KB的容量格式显示
-m:以MB的容量格式显示
示例1:列出当前目录下所有档案容量
如图所示,当不加参数时,du会分析当前目录下所有档案容量,但实际显示只显示目录容量,不含文件。单位为KB。
示例2:同示例一,但要连文件的容量一起列出来
示例3:列出根目录下每个目录的占用量
如图所示,单位为MB,根目录下的目录用通配符*表示。初期最大的就是/usr了。-s参数表示仅显示该目录占用多少容量。
关于-S参数,由于du默认将所有档案大小都列出,所有档案大小,包括此目录的容量也会被计算一次,最终的容量也会加总一次,加上-S的选项,可以取消次目录的加总,得出该目录下所有档案容量。
Linux下的连结档有两种,一种是类似Windows快捷方式的档案,可以迅速链接到目标档案或目录。另一种是通过文件系统的inode连结来产生新档名。这种连结档称为实体链接(hard link)。
两个档案对应同一个inode号码。
在上面的文件系统中我们知道,inode中存储了档案的权限和属性以及档案实际数据所在的block号码。如果两个档案有同一个inode号码,可想而知这两个档案的权限属性完全相同,实际数据所在的block号码也是同一个。可以理解为一份数据有2个档名。不论使用哪个档名来编辑数据,数据都是写入同一个inode和block中去。删除其中一个档案档名,该档案的inode和block还是存在的。
根据这个特性,我们能推断出,设置一个文件的hard link时,不会造成未使用的block和inode数量的改变,因为它不产生新的block和inode。
Hard link的限制:
在linux中,目录和文件都是档案,而linux存储目录和文件的方式都相同,都是将权限和属性以及内容所在的block号码放置在inode号码中,而内容放置在inode中。
唯一不同的是,放置目录内容的block中还放置了目录下各个档案所在的inode号码,而放置文件内容的block中仅放置内容,无inode号码。而这个inode号码用于连接目录下的各个文件。
如果用hard link对目录创建连接,那么目录下各个档案都必须要一一对应创建连接,这样会导致一个很复杂的环境。
创建连接要用ln指令。
ln [-sf] 来源文件 目标文件
-s:如果不添加任何参数进行连接,那就是hard link。添加-s就是symbolic link
-f:如果目标文件已存在,主动将目标文件移除后再建立。
示例1:新建文件并对该文件创建3个hard link。修改其中一个文件,看源文件内容是否改变,删除其中一个文件呢?
首先我创建一个档案~/test.txt,内容如图所示
对该文件创建3个hard link,命名为test1.txt,test2.txt,test3.txt
如图所示,这几个文件的权限属性包括创建时间和源文件的都是一样的,而他们的inode号码也是同一个。
注:这里来源文件指的是被连接的原文件,目标文件是指建立连接的文件,该文件原来并不存在,在ln指令执行时才被创立。
访问任意一个文件,内容和源文件是一样的。
修改任意一个文件,这四个文件的内容都被修改
如图,我对test1.txt进行修改,四个文件的内容都被修改
删除源文件,我们是否还能通过test1.txt文件访问呢
如图所示,一个连结档中建立连接的任何文件被删除,都能通过连接内其他文件访问文件内容,因为inode和block并没有被删除。
示例2:给目录做hard link会发生什么事呢
如图所示。~/test目录下有两个文件~/test/regular_express.txt和~/test/.tcshrc。对~/test目录建立hard link。
如图所示,提示hard link not allowed for directory。Hard link是不能对目录建立的。
Symbolic link相当于Windows系统内的快捷方式,就是建立一个独立的档案,该档案会让数据的读取指向他链接的那个档案的档名。
示例1:对~/test.txt档案建立symbolic link
~/test.txt内容如图所示
对~/test.txt档案建立symbolic link
如图所示,同样test1.txt原先并不存在,是在ln指令执行时被建立的档案。建立symbolic link后,目标文件的后面就会有箭头指向源文件,这是和hard link的一个不同点,hard link没有。对比目标文件和源文件我们发现,这两者的inode号和属性权限也是不同的,说明他们两个是两个独立的档案。为什么test1.txt大小是8bytes呢,因为箭头右边的档名test.txt总共8个字符。每个英文字符占用1个byte。我们可以通过test1.txt访问test.txt。
示例2:承接示例1,修改test1.txt的内容,观察test.txt内容是否改变
如图,两者内容都发生了改变。
示例3:删除源文件,再去访问目标文件。
如图所示,删除了源文件后,再去访问目标文件,提示no such file or directory,而通过ls -ail指令查看,我们发现test1.txt和它所指向的文件都标红了,而test.txt没有被显示出来,说明test.txt确实是被删除了。这放在Windows系统里面叫:test1.txt是无效的快捷方式。
注:symbolic link建立的档案是一个独立的新档案,所以会用掉inode和block。
示例4:对~/test目录建立symbolic link
如图所示。~/test目录下有~/test/regular_express.txt和~/test/.tcshrc两个档案,对~/test目录建立symbolic link,将目标档案命名为test1。
如图所示,对目录建立symbolic link是能够成功建立的。
但是test1和test的档案类型是有区别的,如图所示,权限那栏的第一个字符,test目录为d,代表的是目录,test1档案为l,代表的是连结档,所以我们用ls -al test和ls -al test1,结果是不同的。如图所示
但是我们对test1使用cd指令,依然能够进入test目录
如图所示,在~/test1下对档案做删除档案,新增档案操作,再去访问test,其实也是对test目录下的档案做删除,新增操作。
当我们新建一个目录时,目录的link数量是多少呢。如图,我在家目录下建立了test目录,会有三个东西被建立
/root/test
/root/test/.
/root/test/..
我们都知道,/root/test/.和/root/test其实是一样的,都是代表该目录,而/root/test/..则代表上级目录/root。所以当我们新建一个目录时,该目录的连结数为2,而上级目录的连结数会加一。
为了方便对比上级目录数量是否加一,我再新建一个目录test1
当我们拿到一个新的磁盘,装在电脑上,以下几个动作是必须做的:
对磁盘进行分割,以建立可用的分区。
对分区进行格式化,以建立系统可用的文件系统
对刚刚建立好的文件系统进行检验
在linux系统上需要建立挂载点(即目录),并将它挂载上来。
但是这个过程中,依然有很多问题需要考虑,比如硬盘分区槽多大,block的大小,是否需要加入日志功能,inode和block的数量等问题。
fdisk [-l] 装置名称
-l:输出后面接的装置的所有partition内容,若后面不接装置,系统会把整个系统中能搜寻到的装置的所有partition都列出来。
示例1:找到根目录所在磁盘,并且查阅该磁盘内的相关信息。
如图所示,fdisk这支程序是完全不需要背指令的,在上图中,执行fdisk后只需要按下m就可以看到所有参数和它对应的意义。其中要注意的是,q表示的是不保存退出,w表示的是保存后退出。
我们先来查看一下分割表信息
输入p,如图所示,/dev/mapper/centos-root目前没有分割表。注:我这边是虚拟机安装,未对磁盘进行分区,所以磁盘是一整块。
在上图中
这里这块内容只是简单提一下,因为我的linux磁盘信息没有可靠的数据,所以略过。
Fdisk指令只有root用户才能执行。
我这边没有数据,只能简述一下步骤:
Fdisk /dev/hdc:先进入fdisk指令环境
p:看一下分割槽信息,假设要删除/dev/hdc1
d:这个时候会要你选择一个partition,选1,因为要删除的是/dev/hdc1
w或者q:保存退出或者是不保存退出
如图所示,进入fdisk指令环境中,首先用p查看分区槽,用n新增分割槽。因为是全新磁盘,只会问你要新建主分区(primary)还是扩展分区(extended),图中我选择了p(primary)然后输入分区号码,我这边设定为1号,起始磁柱就选择默认值,直接回车就可以了,结束磁柱号码那里我输入了+512M,并没有输入磁柱号码,意思是让系统自动帮我们找出大概512M大小的分割槽的结束磁柱。
最后我们输入p来查看分割槽,刚刚建立的分割槽名为/dev/mapper/centos-root1。
一般来说建立分割槽的形式有以下几种:
此时会让你挑选primary/extended的项目,且你可以指定1-4之间的号码
此时会让你挑选primary/logical的项目,若选择p需要指定1-4之间的号码,而选择l则由系统自动指定逻辑分割槽的文件名号码
此时不会让你挑选分割槽类型,而是直接进入logical的分割槽形式。
总之,系统只能建立1个extended,建立好之后,只能在extended中建立logical。
当分区完成之后保存,系统会要求reboot,因为linux核心无法重新取得分割槽信息,所以需要我们reboot来更新核心的分割槽信息。
但是你可以通过GUN推出的partprobe指令来绕过reboot,这个指令的作用是告知核心必须要读取新的分割槽,这样我们就不需要reboot了。
以root身份进行硬盘的partition时,最好在单人维护模式下比较安全。操作时如果提醒某个partition正在被使用,那么系统核心就无法重载新的partition table,最好的办法是卸除该被使用的partition,重新新建partition。
SATA硬盘是最常见的硬盘,最多能支持到15号的分割槽,IDE的硬盘可以支持到63号。因此如果SATA硬盘的分割槽超过了15号,即使还有剩余的磁柱容量,也无法再新建分割槽。且fdisk指令无法处理2TB以上的分割槽。高于2TB以上的磁盘系统应该使用parted指令。
磁盘格式化的指令为mkfs(make filesystem),这个指令会去呼叫正确的文件系统格式化工具,是个综合性的指令。
mkfs [-t 文件系统格式] 装置文件名
-t:可接文件系统格式,如Ext2,Ext3,XFS等。
例如,将/dev/hdc6格式化为Windows可读的vfat格式,要这样写
mkfs -t vfat /dev/hdc6
mkfs是个综合性的指令,执行上列语句时,系统会去调用mkfs.vfat指令来进行格式化动作。但这个指令我们没有详细指定文件系统的详细参数,所以格式化是按照默认值来进行的。如果想要详细指定文件系统的标头(label)、block的大小以及inode的数量,就需要认识Ext2/Ext3的公用程序,即mke2fs。
由于我这边的文件系统不是Ext2/Ext3的,所以mke2fs我就不给出示例了。
mke2fs [-b block大小] [-i inode大小] [-L 标头] [-cj] 装置文件名
-c:检查磁盘错误,仅下达一次-c时会进行快速读取测试,下达两次-c -c的话,会进行读写测试,会很慢
-j:加上-j后会加入日志,格式化为Ext3文件系统
进行如下设定:
文件系统标头:huyan_logical
Block大小:2K
每8192bytes分配一个inode
建置为journal的Ext3文件系统
那么代码应该这样写:
mke2fs -j -b 2048 -i 8192 -L “huyan_logical” /dev/hdc6
如果发生内存和磁盘内数据异步的情况,导致文件系统错乱,就需要fsck这个好用的文件系统检验指令。
fsck [-t 文件系统] [-ACay] 装置名称
-t:fsck和mkfs一样也是一个综合软件,需要我们指定文件系统。但linux会自动通过superblock去辨别文件系统,所以一般不需要用到这个参数。
-A:根据/etc/fstab的内容,将需要的装置扫描一次。
-a:自动修复检查到的有问题的扇区。
-y:功能与-a类似,但有些文件系统仅支持-y这个参数。
-C:在检验过程中使用直方图来显示目前的进度。
示例1:看看到底有多少文件系统支持fsck软件
fsck是用来检查与修正文件系统错误的指令。每次执行fsck时其实呼叫的是e2fsck这个指令。只有在身为root和你的文件系统有问题的时候才可以使用这个指令,因为用fsck扫描硬盘,可能会造成部分文件系统的损坏,所以被扫描的partition不能挂载在系统上,必须处于卸除状态。
我这边没有这种数据,不做示例了。
注:在ext2/ext3文件系统挂载点的目录下面,会出现lost+found这个目录,这个目录就是用来存放fsck检查文件系统后发现的有问题的数据。所以一般这个目录是没有数据的,如果有数据,那么你就要格外注意你的文件系统了。
所以这边推荐了另外一个指令:xfs_repair。
xfs_repair [-n] 装置文件名
Badblocks指令用于检查磁盘坏道。
Badblocks [-svw] 装置名称
-s:在屏幕上列出进度
-v:可以在屏幕上看到进度
-w:使用写入的方式来测试,建议不要使用此参数,尤其在待检查的装置已有档案时
由于这个指令可以透过“mke2fs -c 装置文件名”在进行格式化的时候处理磁盘表面的读取测试,所以目前大多不使用这个指令了。
文件系统的挂载与卸载用mount指令。在挂载文件系统之前我们必须要了解一下几点:
如果不是空目录,假如新的硬盘并挂载后,目录下面显示的是新分割槽中的内容,而原来目录下的内容会被暂时隐藏,直至硬盘被卸载后才会重新显示。
mount -a
-a:依据配置文件/etc/fstab中的内容将所有未被挂载的磁盘都挂载上来
mount [-l]
-l:不加-l参数显示的是目前挂载的信息,假如-l增加label标头列的显示
mount [-t 文件系统名] [-L Label名] [-o 额外选项] [-n] 装置文件名 挂载点
-n:在默认情况下,系统会将实际挂载情况写入/etc/mtab中,但在某些情况(例如单人维护模式下)可以用-n刻意不写入。
-o:后面可以接一些参数,比如账号,密码,读写权限等
ro,rw:挂载的文件系统可读或者可写
sync,async:是否使用同步(sync)或异步(async)写入内存机制
等等,还有很多,这里不一一举例了。
示例1:用默认的方式将/dev/hdc6挂载到/mnt/hdc6上面
执行下列命令:
mkdir /mnt/hdc6
mount /dev/hdc6 /mnt/hdc6
只要使用“mount 设备文件名 挂载点”就能够成功挂载了,并不需要使用-t这个参数来指定文件系统名。这是因为文件系统几乎都有super block,Linux可以通过分析super block搭配自己的驱动程序去测试挂载。测试成功,就立刻自动使用该类型的文件系统挂载起来。
系统指定需要进行上述挂载测试的文件系统类型主要是参考下面两个文件:
/etc/filesystems:系统指定的测试挂载文件系统类型;具体内容如图所示
/proc/filesystems:Linux系统已经加载的文件系统类型;具体内容如图所示
而相关文件系统类型的驱动程序被写在下面的目录中:
/lib/modules/$(uname -r)/kernel/fs/
具体内容如图所示
示例2:查看目前已挂载的文件系统,包含各文件系统的label名称
示例1:将你用来安装Linux的CentOS原版光盘挂载
初次挂载时要创建挂载点,然后才可以进行挂载。执行下列语句
mkdir /media/cdrom
mount /dev/cdrom /media/cdrom
当然也可以通过-t参数指定挂载的文件系统类型。在这里,/dev/cdrom只是个连接文件,我的光驱接在/dev/hdd中,因此正确的挂载语句应该是“mount /dev/hdd /media/cdrom“。光驱一旦挂载后就无法退出光盘,除非将光驱卸载。
软盘的格式化直接使用mkfs即可。
示例1:将软盘格式化为Windows和Linux都可以使用的FAT格式,然后挂载到/media/floppy/目录中。执行下列命令
mkfs –t vfat /dev/fd0
mkdir /media/floppy
mount –t vfat /dev/fd0 /media/floppy
与光驱不同的是,软盘被挂载后依然可以退出软盘,但退出软盘之后文件系统就会有莫名其妙的问题发生。整个Linux最重要的就是文件系统,而文件系统是直接挂载到目录树上头,几乎任何命令都会或多或少地使用到目录树的数据,因此不可以随意将光盘/软盘拿出来。要拿出来也请卸载了之后再退出。
示例1:找出U盘的设备文件名并挂载到/mnt/flash目录中
这里我们需要用到fdisk –l指令来列出整个系统能够找到的设备的分区
fdisk –l
mkdir /mnt/flash
mount –t vfat –o iocharset=cp950 /dev/sda1 /mnt/flash
带有中文文件名的数据,可以在挂载时指定一下挂载文件系统所使用的语言,通过man mount查找手册,我们可以知道vfat文件格式当中可以使用iocharset来指定语系,而中文语系是cp950。
整个目录树最重要的地方就是根目录了,根目录是不能够被卸载的,可是万一挂载参数发生改变,或者根目录出现只读状态时,最可能的处理方式就是重新启动,但是你也可以选择重新挂载。
示例1:将根目录重新挂载,并加入参数rw和auto
执行下列语句
mount –o remount,rw,auto /
请注意“-o remount,xx”参数,要重新挂载时,这是个非常重要的机制,尤其是进入单用户模式时,根目录常被系统挂载为只读。
另外,我们也可以利用mount将某个目录挂载到另外一个目录去,这不是挂载文件系统,而是额外挂载某个目录的方法。虽然我们也可以使用symbolic link来连接两个目录,但在某些不支持符号连接的程序运行中,还是得要通过挂载目录的方法。
示例2:将/home目录挂载到/mnt/home下面
如图所示,利用—bind参数,可以将某个目录挂载到其他目录去,而不是整块文件系统,并且通过ls –lid语句我们发现,/home与/mnt/home有相同的inode号码,这是不是像极了我们的hard link呢?
umount [-fn] 设备文件名或挂载点
-f:强制卸载,可用在类似网络文件系统(NFS)无法读取到的情况下
-n:不更新/etc/mtab的情况下卸载。
注:默认情况下,系统会将实际挂载情况写入/etc/mtab中。这个后面会说到。
示例1:将上面示例2中的/home目录解挂
如图所示,执行umount /mnt/home语句,这样/home和/mnt/home又有不同的inode号码了。如果挂载的是文件系统,可以用挂载点和设备文件名来卸载,但如果挂载的是目录,只能通过挂载点来卸载,写法也是和示例中一样。如果在卸载过程中提示device is busy,这说明你正在使用该文件系统,所以无法卸载这个设备,离开该文件系统的挂载点再执行语句即可。
除了磁盘的设备文件名外,我们还可以使用文件系统的卷标名称来挂载。
示例1:找出/dev/hcd6卷标名称,并用label挂载到/mnt/hdc6。
我们可以用dumpe2fs指令找出卷标名称,因为我这边的文件系统类型是XFS,不支持这个指令,所以这边就说一下不演示了。
执行下列指令
dumpe2fs –h /dev/hdc6
mount –L “vbird_logical” /mnt/hdc6
注:利用-L参数可以使用label name进行挂载。卷标名称再代码中要用引号括起来。这种挂载方法的好处是,系统不必知道该文件系统所在的接口与磁盘文件名。
如果你想要修改label name或者journal等相关磁盘参数,就要用到下面的命令了
Linux下所有装置都以档案的形式来表示,而linux系统是根据major和minor这两个数值判断哪个档案代表的是哪个装置的。这两个数值被称为装置代码。
如图,在我的linux系统中用到的磁盘/dev/sda相关装置代码如下
图中8代表的就是major数值,0,1,2代表的就是minor数值。
常见的硬盘文件名/dev/hda和/dev/sda装置代码如下
磁盘文件名 | Major | Minor |
---|---|---|
/dev/hda | 3 | 0~63 |
/dev/hdb | 3 | 64~127 |
/dev/sda | 8 | 0~15 |
/dev/sdb | 8 | 16~31 |
mknod的语法和参数
Mknod 装置文件名 [bcp] [Major] [Minor]
b:设定装置名称为一个周边存储设备档案,如硬盘等
c:设定装置名称为一个周边输入设备档案,如键盘,鼠标等
P:设定装置名称为一个FIFO档案
Major:主要装置代码
Minor:次要装置代码
示例1:从上图中我们知道/dev/sda3的装置代码为8,3,建立并查阅这个装置
示例2:建立一个FIFO档案,档名为/tmp/testpipe
这个档案不是一般档案,不可以随便放在这里,测试完后用rm指令删除。
文件系统格式化完成后如果要修改标头(label name),可以用e2label指令来修改。目前CentOS的配置文件,也就是/etc/fstab档案都预设使用label name。
e2label 装置名称 新装置名称
tune2fs [-jlL] 装置代号
-l:类似于dumpe2fs -h的功能,将分区槽的super block读取出来
-j:将ext2文件系统转换成ext3文件系统
-L:类似e2label的功能,可以修改文件系统的label name
这边因为我是XFS文件系统,所以不适用这个命令,不举例了。以后会出一个关于磁盘和文件系统命令的XFS版文档。
如果你的硬盘是IDE接口的,这个指令用于设定一些进阶参数,如果是SATA接口,这个指令就没有多大用处了。
用mount指令手动挂载太麻烦了,我们得想办法让系统在开机时自动挂载文件系统。
当我们用mount指令对文件系统进行挂载时,参数会被写入到/etc/fstab这个档案中。
/etc/fstab内容如图所示
这个档案的内容共6个字段。
开机过程中,系统会默认用fsck指令检验文件系统是否完整。但是某些文件系统是不需要检验的,如swap(内存交换空间),特殊文件系统/proc和/sys等等。0代表不检验,1代表最早检验,2代表稍晚检验,一般根目录设置为1,其他文件系统设置为2。
文件系统参数表
参数 | 内容意义 |
---|---|
async/sync 异步/同步 |
设定磁盘以异步方式运作还是同步方式运作,一般以async运作效能较佳 |
auto/noauto 自动/非自动 |
当下达mount -a时,此文件系统是否会被主动测试挂载。预设为auto |
rw/ro 可擦写/只读 |
让该分割槽以可擦写或者只读状态挂载上来。如果设置为只读,在该文件系统的档案即使有w权限也无法被修改 |
exec/noexec 可执行/不可执行 |
此文件系统以可执行或不可执行状态挂载,如果是不可执行的,那么即使文件系统内的档案有x权限也无法被执行 |
user/nouser 允许/不允许使用者挂载 |
是否允许用户用mount指令挂载。一般用nouser,用user太不安全了 |
suid/nosuid 具有/不具有suid权限 |
该文件系统是否允许SUID存在,如果不是执行文件放置目录,一般设置为nosuid |
usrquota | 启动文件系统时支持磁盘配额模式 |
grpquota | 启动文件系统时支持群组磁盘配额模式 |
defaults | 同时具有rw,suid,dev,exec,nouser,auto,async参数,一般来说用default即可 |
假设我们要将/dev/hdc6每次开机都挂载到/mnt/hdc6该如何进行?
首先,执行nano /etc/fstab,编辑/etc/fstab文件,添加下列行,保存并退出。
/dev/hdc6 /mnt/hdc6 ext3 default 1 2
执行df指令看看/dev/hdc6是否已挂载,如果已挂载,必须先用amount /dev/hdc6卸除。
然后用mount -a和df测试一下刚刚输入的语法有没有错误,如果有错误会导致开机开不起来。
/etc/fstab是开机时的配置文件,实际上文件系统的挂载是记录到/etc/mtab和/proc/mounts这两个文件中的。每次我们变动文件系统的挂载时,这两个文件都会变动,如果上面在/etc/fstab中的设置出现错误导致无法开机,而进入单人维护模式中,那时根目录是read only状态,我们无法修改/etc/fstab,也无法更新/etc/mtab。我们可以执行下列语句
mount -n -o remount,rw /
上面语句的意思是重新挂载根目录,挂载状态为可擦写,但挂载情况不写入/etc/mtab中。
当我们从国家高速网络中心(http://ftp.twaren.net)或者义守大学(http://ftp.isu.edu.tw)下载了linux镜像文件,难道一定要刻录成为光盘才能够使用档案里的数据吗?我们可以通过mount的特殊参数loop来挂载的。
假设系统中有一个centos5.2_x86_64.iso文件,放在/root目录下
用下列指令将该镜像文件挂载到/mnt/centos_dvd目录下
mkdir /mnt/centos_dvd
mount -o loop /root/centos5.2_x86_64.iso /mnt/centos_dvd
再用df指令查看是否挂载上去了。
如果挂载上去了,那么centos5.2_x86_64.iso镜像文件的所有内容都可以在/mnt/centos_dvd目录下看到。这样一来,我们不需要通过刻录光盘来读取镜像文件中的数据了,同时还可以修改镜像文件中的数据。这也就是很多镜像文件提供后还要提供MD5验证码给使用者以确认该镜像文件没有问题。
我们还可以将一个大容量档案,格式化后用loop挂载。这能够帮助我们解决系统分割不良的问题,假如在分割时只分割出一个根目录,磁盘也没有多余的容量可以进行额外的分割,偏偏根目录下的可用容量还很多,这时我们就可以建立一个大容量档案挂载到根目录下,相当于多了一个分割槽。
Linux系统下有一只很好用的指令dd,可以用来建立空档案。
这个指令的简单意义如下,if为input file,输入档案,/dev/zero是一个会一直输出0的装置,of为output file,将数据输出到/home/loopdev中,bs表示block大小为1M,这个block概念跟文件系统的block概念是一样的。count规定了总共有512个block,即规定文件大小为512M。
下面的512+0 records in和512+0 records out表示/dev/zero正在输入数据,并将数据输出到/home/loopdev档案中。
利用mount的特殊参数-o loop将/home/loopdev挂载到/media/cdrom/目录
通过这种方法,就可以在原本的分割槽不变动原有环境的情况下制作出你想要的分割槽。
Linux系统安装时一定需要的两个分区,一个是根目录,一个是swap,又名内存交换空间。swap有在物理内存不足的情况下内存延伸记录的功能。如果物理内存足够,swap是不会被使用到的。CPU读取的数据来自于内存,当物理内存不足时,为了让后续程序顺利运作,因此物理内存中暂不使用的数据就会被移动到swap中,空出来空间给需要执行的程序加载数据。而swap是用硬盘来暂时存放内存中的数据的。
如果linux系统已经安装好,才发现没有建立swap分区,就可以用下面两种方法构建swap。
用fdisk指令在磁盘中分割出一块分割槽给swap,因为fdisk默认将分割槽的ID设定为linux格式,所以还需要设定一下system ID,swap的ID是82号。
如图所示,建立了一个分割槽,但ID是83,为linux系统。将ID修改为82。
最后输入w保存并退出,分割槽就建立好了。建立好分割槽之后不要忘记执行partprobe指令让核心更新分割表。
执行mkswap /dev/sda1p1将分割槽格式化为swap格式
用free指令可以观察内存使用量,如图所示
目前swap总量为2G,没有内存被使用。
执行swapon /dev/sda1p1指令开启swap,然后用free -h指令观察swap总量,会发现数值有增加。
注:用swapon -s可以列出目前使用swap的装置有哪些。
如果实体分割槽没有空间可以分割了,可以使用上面提到过的用loop构建大档案挂载的方式。
使用dd指令在/tmp下新建一个128M的档案
将/tmp/swaptest文件格式化为swap格式
使用swapon将/tmp/swaptest启动
如图所示,swap启动前和启动后,free指令查询出来的swap总量变化了。
用swapoff指令将swap关闭
就现在的桌面计算机而言,内存容量至少也有512M,swap存在的意义已经不大了。但是对于linux服务器及工作站这种需要常年在线的系统来说,建立swap还是很有必要的。Swap的功能是,当物理内存不足时,将物理内存中暂时不需要被可执行程序使用的数据转移到swap(其实也是转移到硬盘)中,让空出来的物理内存可以被需要的程序使用。
如果你的主机支持电源管理模式,当主机休眠时,程序状态会被记录到swap中,作为唤醒主机的状态依据,另外有一些程序会利用swap的特性来存放一些数据,所以swap还是有必要被建立的。
Swap有一些使用上的限制:
如图所示,我们在前面学到,Linux的文件系统将,可安装开机信息的boot sector(启动扇区)独立出来,并非放置到super block中。但其实也并不一定如此,视block的大小而定。
Super block大小为1024bytes
Super block前面要空出1024bytes来用于启动扇区。
当block为1K时,boot sector和super block正好各自占用1K,也就是上图中的情况。Boot sector占用0号block,super block占用1号block。
当block大于1K(2K或4K)时,为了防止浪费空间,boot sector和super block都存储在0号block中,如果0号block还有空间剩余则保留。
因为1个block只能放置1个档案的数据,之前我们就有提到过关于磁盘空间浪费的问题。但其实整个文件系统中包括super block,inode table与其他数据都会浪费磁盘空间。
另外,当我们用ls –l指令去查询目录下档案数据时,第一行都会出现total值,这个值其实就是该目录下所有数据所占用的实际block数量×block大小的值。如下图所示:
每个文件前面都标出了该文件所用的block大小,此系统的1个block大小为4K,由此可以推断出存储该档案用了几个block。而total的数量即是存储目录下所有档案花的block大小,这个数据是绝对大于目录下档案实际大小总和的。而total减去档案实际大小总和,就是被浪费的空间大小。
也就是说,我们花了44KB去存储总共10.9KB大小的档案。
此外,我们通过du指令查询目录所占用的所有空间,比较发现如图:
用byte形式表示,/root目录占用了31051bytes,换算应该约等于30.3KB左右,但使用block去测试,就会发现此时该目录占用了1M的空间,浪费了大约994KB空间。
先前我们学过的磁盘分区指令fdisk无法支持到大于2TB的分区,此时就需要parted来处理了。parted可以直接用一行命令完成分区,是个很好用的工具。
parted的语法和参数
parted [设备] [命令 [参数]]
命令:
新增分区:mkpart [primary|logical|extended] [ext3|vfat] 开始 结束
分区表:print
删除分区:rm [partition]
示例1:用parted指令列出本机分区表
如上图,先找到系统所有能找到的分区
如图所示,model表示硬盘接口与型号为unknown,disk /dev/sda1:1074MB表示磁盘文件名是/dev/sda1,容量为1074MB。Sector size(logical/physical):512B/512B表示每个逻辑和物理扇区的大小都是512B。Partition table:loop表示分区表形式为loop,接下来显示的就是分区表。
number表示分区号码,1号代表的是/dev/sda1的意思。
start表示起始柱面的位置,它以容量作为单位。
end表示结束柱面的位置。
size表示该分区的容量大小。
file system表示文件系统类型。
示例2:新建一个约为512MB的逻辑分区(因为我的磁盘空间已经满了,无法新建分区,这里拿鸟哥书上的例子来讲)
执行指令parted /dev/hdc mkpart logical ext3 19.2GB 19.7GB
上述指令中/dev/hdc是硬盘设备名,logical代表逻辑分区,ext3表示文件系统类型为ext3,上个分区的结束柱面位置是在19.2GB处,因此,新建的柱面起始位置应该也在19.2GB处,大小为0.5GB,因此柱面结束位置填写19.7GB。
这里就新建好了,接下来使用parted /dev/hdc print查看分区表就行了。
示例3:将示例2中建立的第八号磁盘分区删除。
执行指令parted /dev/hdc rm 8
这样就删除了,执行这个指令要格外注意,一旦enter就立刻生效,所以不能写错。