i节点、文件目录以及硬链接和软链接

当Unix创建文件时,Unix完成两件事情:第一,Unix在存储设备上保留一块空间用来存储数据。第二,Unix创建一个称为索引节点(index node)或i节点(i-node)的结构,来存放文件的基本信息。i节点包含使用文件所需的全部文件系统信息。在Linux系统上,可以通过使用stat命令(stat filename),方便地查看某个特定文件的i节点的内容。
1、i节点表和i节点号
文件系统将所有的i节点存放在 一个大表中,这个表称为i节点表(inode table)。在i节点表中,每个i节点由所谓的索引号(index number)或i节点号(i-number)表示。可以使用带-i选项的ls命令(ls -i filename)查看文件的i节点号。
2、目录
所有的文件都存储为一个单独的实体。目录并不存包含文件,它只是包含Unix定位文件所需的信息。实际上,目录只包含文件的名称及文件的i节点号。因此,目录的内容相当小:只有一列名称,每个名称对应一个i节点号。具体地,当在bin目录中创建文件spacewar时,首先,Unix在硬盘上保留存放该文件的存储空间。接下来,Unix查看i节点表,查找一个空闲的i节点(如果没有空闲的i节点,则创建一个新的i节点)。假设Unix查找到的i节点是#478515。然后,Unix将信息填充到属于该新文件的i节点中。最后,Unix在bin目录中放入一个条目。该条目包含名称spacewar,以及一个为478515的i节点号。每当程序需要使用文件时,程序在目录中查找文件名时将是一件简单的事情,只需使用相应的i节点号查找i节点,然后使用i节点中的信息访问文件即可。
3、链接
文件名和i节点之间的连接称为链接。从概念上讲,链接将文件名和文件本身连接起来,这就是为什么i节点中不包含文件名。实际上,一个i节点可以由不止一个文件名引用。
Unix文件系统最出色的特征就是允许多重链接。也就是说一个文件可以有不止一个名称。文件的唯一标识是其节点号,而不是它的名称。因此,多个文件名可以引用同一个i节点号。比如在home目录下,有一个game.txt文件,用ln命令(ln game.txt happy.txt)可以为game.txt创建一个新的链接该链接对应文件名happy.txt。实际上,game.txt和happy.txt对应一个相同的i节点号,该i节点号指向的i节点中包含了实际的一个文件在物理磁盘上存储的信息,这个文件在操作系统层面上可以通过文件名game.txt和happy.txt进行访问。
物理磁盘上存储的文件与i节点一一对应,而文件名与该物理文件的链接一一对应。一个物理文件可能对应对个链接,这样一个物理文件可以对应多个文件名,而且可以存在于多个不同的目录位置。也就是说,文件不由它们的名称或位置控制,名称和位置对应的只是一个指向物理文件的链接。这一设计的依据在于,取决于文件不同的使用环境,同一个文件可能拥有不同的含义。
到这里可能有个疑问,假设一个文件拥有不止一个链接,即该文件可以通过不止一个名称进行访问。那么哪个名称最重要呢?原始的名称是不是有特殊的含义呢?不是的,Unix平等地对待所有的链接,而不会去关心该文件的原始名称是什么,新链接和旧链接拥有同等的重要性。
4、文件目录相关操作
实际上,基本的文件操作命令(mkdir、cp、mv、rm、ln)都是基于链接的。
创建文件、创建目录[mkdir]
创建新文件或目录时,Unix会留出相应的存储空间并创建i节点。然后Unix在适当的目录中通过使用指定的文件名或目录名以及新节点的i节点号置入一个新的条目。
  4.1 复制文件[cp]
如果复制操作要覆盖目标文件时(比如cp f1 newf1,而newf1已经存在),Unix用源文件的内容替换目标文件的内容,但是i节点号并不进行修改;如果复制操作要产生一个原来不存在的文件时(比如cp f1 newf1,newf1不存在),Unix首先用新文件自己的i节点号(通过查找i节点表有无空闲获得,若无空闲,则新建一个i节点)创建一个全新的文件,然后将旧文件的内容复制到新文件中。在复制之后,将会有两个相同的文件,老文件名对应于老的i节点号,新文件名对应于新的i节点号。
  4.2 重命名文件或移动文件[mv]
重命名或移动文件时,Unix改变文件名,或者移动目录条目,或者两者都进行,但是保持相同的i节点号。这就是同一条命令(mv)既可以重命名文件,又可以移动文件的原因。
  4.3 创建链接[ln]
创建已有文件的新链接时,Unix使用指定的文件名创建一个新的目录条目,并指向原始文件的i节点号。这样,一个文件拥有两个文件名,但是两个文件名指向同一个i节点号。
  4.4 移除链接[rm、rmdir]

实际上,删除命令都是移除的都是文件的链接。移除连接时,Unix通过移除目录条目,消除文件名和i节点号之间的链接。如果已经没有链接,Unix会删除该文件。(删除链接和删除文件不是一个概念,如果文件还有不止一个链接,那么Unix不会删除文件,直到移除最后一个链接。但是,在大多数情况下,文件只有一个链接,因此,大多数情况下,rm和rmdir都充当删除命令。)

4.5 硬链接和软链接

上面介绍的链接称为硬链接,只能对一个文件创建硬链接,没法对目录创建硬链接。与硬链接对应的还有一种链接,称为软链接,也叫符号链接(symbolic link)。软链接有点类似于windows的快捷方式。实现层面上来说,它是一个特殊的文本文件,其中包含着目标文件的位置信息。要注意的是创建软链接的时候最好采用绝对路径,这样,保证链接文件移动到其它目录之后,仍然可用,下面演示了硬链接和软链接的区别和使用:

//新建一个空目录
[lfqy@localhost ~]$ mkdir temp
//在该目录中创建一个文本文件
[lfqy@localhost ~]$ cd temp/
[lfqy@localhost temp]$ echo "This is test.txt file! ^_^" > test.txt
//为该文件创建两个硬链接
[lfqy@localhost temp]$ ln test.txt test.hlink
[lfqy@localhost temp]$ ln test.txt test.hlink1
//通过两个硬链接都可以访问该文件
[lfqy@localhost temp]$ cat test.hlink
This is test.txt file! ^_^
[lfqy@localhost temp]$ cat test.hlink0
cat: test.hlink0: No such file or directory
[lfqy@localhost temp]$ cat test.hlink1
This is test.txt file! ^_^
//为该文件创建一个软链接
[lfqy@localhost temp]$ ln -s test.txt test.slink
//通过软链接也可以访问该文件
[lfqy@localhost temp]$ cat test.slink 
This is test.txt file! ^_^
//创建一个子目录test,并在其中创建一个文本文件
[lfqy@localhost temp]$ mkdir test
[lfqy@localhost temp]$ cd test
[lfqy@localhost test]$ echo "This is a h.txt in test directory! >_<" > h.txt
[lfqy@localhost test]$ cd ..
//不可以为目录创建硬链接
[lfqy@localhost temp]$ ln test test.hlinkdir
ln: `test': hard link not allowed for directory
//但是,可以为目录创建软链接,并通过该软链接来访问该目录
[lfqy@localhost temp]$ ln -s test test.slinkdir
[lfqy@localhost temp]$ cat test.slinkdir/h.txt 
This is a h.txt in test directory! >_<
//可以看到软链接会显示一个指向目标文件的箭头
[lfqy@localhost temp]$ ls -al
total 24
drwxrwxr-x.  3 lfqy lfqy 4096 May  4 01:26 .
drwx------. 32 lfqy lfqy 4096 May  4 01:21 ..
drwxrwxr-x.  2 lfqy lfqy 4096 May  4 01:25 test
-rw-rw-r--.  3 lfqy lfqy   27 May  4 01:22 test.hlink
-rw-rw-r--.  3 lfqy lfqy   27 May  4 01:22 test.hlink1
lrwxrwxrwx.  1 lfqy lfqy    8 May  4 01:23 test.slink -> test.txt
lrwxrwxrwx.  1 lfqy lfqy    4 May  4 01:26 test.slinkdir -> test
-rw-rw-r--.  3 lfqy lfqy   27 May  4 01:22 test.txt

要注意的是,当一个物理文件的最后一个硬链接被删除的时候,该文件才会被删除。删除软链接就和删除windows的一个快捷方式一样,对物理文件没影响。

4.6 链接的应用

有一台服务器上跑mongodb,但是,mongodb的更新比较活跃,为了使用mongodb的新的特性经常要升级mongodb,甚至有些时候,要回退到老版本的mongo。链接在这里的用法是:将各个版本的mongodb(官网上的mongodb下载下来解压,肯定得到一个包含bin等子目录的目录,其中有mongodb的二进制文件)放在一个目录下比如temp。这样temp下便有了各个版本的mongodb目录,比如mongodb2.0、monogodb2.2、mongodb2.4等,然后创建一个软链接mongodb,这样名为mongodb的软链接指向哪个目录系统用的就是那个目录。所有的启动命令之类的可以用软链接来访问,比如mongodb/bin/mongod。如果有新的mongo版本发布,将其下下来放到该目录更改原来软链接文件的指向就行了,其它的都不用改。

如果将mongodb的启动,用supervisor托管,那么就更方便了。^_^

参考书目:《Unix&Linux大学教程》(美)Harley Hahn著

你可能感兴趣的:(unix,链接,文件系统,i节点,文件目录操作的链接意义)