文件系统就是分区或磁盘上的所有文件的逻辑集合。
文件系统不仅包含着文件中的数据而且还有文件系统的结构,所有Linux 用户和程序看到的文件、目录、软连接及文件保护信息等都存储在其中。
不同Linux发行版本之间的文件系统差别很少,主要表现在系统管理的特色工具以及软件包管理方式的不同,文件目录结构基本上都是一样的。
文件系统有多种类型,如:
目录 | 说明 |
---|---|
/ | 根目录,只能包含目录,不能包含具体文件。 |
/bin | 存放可执行文件。很多命令就对应/bin目录下的某个程序,例如 ls、cp、mkdir。/bin目录对所有用户有效。 |
/dev | 硬件驱动程序。例如声卡、磁盘驱动等,还有如 /dev/null、/dev/console、/dev/zero、/dev/full 等文件。 |
/etc | 主要包含系统配置文件和用户、用户组配置文件。 |
/lib | 主要包含共享库文件,类似于Windows下的DLL;有时也会包含内核相关文件。 |
/boot | 系统启动文件,例如Linux内核、引导程序等。 |
/home | 用户工作目录(主目录),每个用户都会分配一个目录。 |
/mnt | 临时挂载文件系统。这个目录一般是用于存放挂载储存设备的挂载目录的,例如挂载CD-ROM的cdrom目录。 |
/proc | 操作系统运行时,进程(正在运行中的程序)信息及内核信息(比如cpu、硬盘分区、内存信息等)存放在这里。/proc目录伪装的文件系统proc的挂载目录,proc并不是真正的文件系统。 |
/tmp | 临时文件目录,系统重启后不会被保存。 |
/usr | /user目下的文件比较混杂,包含了管理命令、共享文件、库文件等,可以被很多用户使用。 |
/var | 主要包含一些可变长度的文件,会经常对数据进行读写,例如日志文件和打印队列里的文件。 |
/sbin | 和 /bin 类似,主要包含可执行文件,不过一般是系统管理所需要的,不是所有用户都需要。 |
$df -k
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/vzfs 10485760 7836644 2649116 75% /
/devices 0 0 0 0% /devices
$
每一列的含义如下:
列 | 说明 |
---|---|
Filesystem | 代表文件系统对应的设备文件的路径名(一般是硬盘上的分区)。 |
kbytes | 分区包含的数据块(1024字节)的数目。 |
used | 已用空间。 |
avail | 可用空间。 |
capacity | 已用空间的百分比。 |
Mounted on | 文件系统挂载点。 |
你可以结合 -h (human readable) 选项将输出信息格式化,让人更易阅读。
du 命令会显示每个目录所占用数据块。根据系统的不同,一个数据块可能是 512 字节或 1024 字节。举例如下:
$du /etc
10 /etc/cron.d
126 /etc/default
6 /etc/dfs
...
$
结合 -h 选项可以让信息显示的更加清晰:
$du -h /etc
5k /etc/cron.d
63k /etc/default
3k /etc/dfs
...
$
这样就为用户提供了统一的接口,屏蔽了硬件设备的细节。Linux将所有的硬件设备看做文件,对硬件设备的操作等同于对文件的操作。
注意:挂载目录可以不为空,但挂载后这个目录下以前的内容将不可用。
需要知道的是,光盘、软盘、其他操作系统使用的文件系统的格式与linux使用的文件系统格式是不一样的,挂载需要确认Linux是否支持所要挂载的文件系统格式。
查看当前系统所挂载的硬件设备可以使用 mount 命令:
$ mount
/dev/vzfs on / type reiserfs (rw,usrquota,grpquota)
proc on /proc type proc (rw,nodiratime)
devpts on /dev/pts type devpts (rw)
$
一般约定,/mnt 为临时挂载目录,例如挂载CD-ROM、远程网络设备、软盘等。
也可以通过mount命令来挂载文件系统,语法为:
mount -t file_system_type device_to_mount directory_to_mount_to
例如:
$ mount -t iso9660 /dev/cdrom /mnt/cdrom
将 CD-ROM 挂载到 /mnt/cdrom 目录。
注意:file_system_type用来指定文件系统类型,通常可以不指定,Linux会自动正确选择文件系统类型。
挂载文件系统后,就可以通过 cd、cat 等命令来操作对应文件。
可以通过 umount 命令来卸载文件系统。例如,卸载 cdrom:
$ umount /dev/cdrom
不过,大部分现代的Linux系统都有自动挂载卸载功能,unmount 命令较少用到。
管理员有两种方式来分配磁盘空间:
命令 | 说明 |
---|---|
quota | 显示磁盘使用情况以及每个用户组的配额。 |
edquota | 编辑用户和群组的配额。 |
quotacheck | 查看文件系统的磁盘使用情况,创建、检查并修复配额文件。 |
setquota | 设置配额。 |
quotaon | 开启用户或群组的配额功能。 |
quotaoff | 关闭用户或群组的配额功能。 |
repquota | 打印指定文件系统的配额。 |
大部分的Linux文件系统(如ext2、ext3)规定,一个文件由目录项、inode和数据块组成:
目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。
ls命令只列出目录文件中的所有文件名:
ls /etc
ls -i命令列出整个目录文件,即文件名和inode号码:
ls -i /etc
操作系统读取硬盘的时候,不会一个扇区一个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个sector组成一个block。
文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。
inode包含文件的元信息内容:(存放除文件名之外的所有文件信息)
inode的大小
inode也会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。
查看每个硬盘分区的inode总数和已经使用的数量,可以使用df -i 命令。
查看每个inode节点的大小,可以用如下命令:
sudo dumpe2fs -h /dev/hda | grep "Inode size"
由于每个文件都必须有一个inode,因此有可能发生inode已经用光,但是硬盘还未存满的情况。这时,就无法在硬盘上创建新文件。
inode号码
每个inode都有一个号码,操作系统用inode号码来识别不同的文件。使用ls -i命令,可以看到文件名对应的inode号码,例如:
ls -i demo.txt
操作系统打开文件:
对Linux系统内部而言,打开文件不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。
表面上,用户通过文件名,打开文件。
系统内部这个过程分成三步:首先,系统在目录项中得到这个文件名对应的inode号码;其次,通过inode号码,获取文件的所有信息;最后,根据inode信息,找到文件数据所在的block,读出数据。
现代常用的有两种共享方式。
Linux系统允许,可以为一个或多个文件名指向同一个inode号码(索引节点中的链接计数count)。这意味着,可以用不同的文件名访问同样的内容;
同时对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为"硬链接"(hard link)。
ln命令:创建硬链接
ln source_file target_file
运行上面这条命令以后,源文件与目标文件的inode号码相同,都指向同一个inode。
inode信息中有一项叫做"链接数",记录指向该inode的文件名总数,这时就会增加1。反过来,删除一个文件名,就会使得inode节点中的"链接数"减1。当这个值减到0,表明没有文件名指向这个inode,系统就会回收这个inode号码,以及其所对应block区域(数据空间)。
这意味着,文件A依赖于文件B而存在,如果删除了文件B,打开文件A就会报错:"No such file or directory"。这是软链接与硬链接最大的不同:文件A指向文件B的文件名,而不是文件B的inode号码,文件B的inode"链接数"不会因此发生变化。
ln -s命令可以创建软链接,语法为:
ln -s source_file target_file