Linux下的链接文件详解

  发布时间:2016-11-24 15:31:55   作者:佚名   我要评论
Linux下的链接文件可以分为硬链接(hard link)与软链接(soft link)。下面小编将详细的讲解Linux下的链接文件,有需要的朋友可以过来看看

ln命令

我们用ln命令创建硬链接或者软链接。其语法为:

ln [options] file link

此命令的第一种形式会创建一个指向file的新的链接,其中options选项,我们只记住一个就行,-s表示创建软链接,而默认会创建硬链接。例如:

# ln -s /usr/src/linux-2.6.32 /usr/src/linux

这里,我们创建了一个符号链接/usr/src/linux,指向真实的Linux源代码目录/usr/src/linux-2.6.32。

我们再举一个例子,演示一下软链接与硬链接的区别,我们创建一个myfile文件,然后再创建一个指向该文件的软链接myslink和硬链接myhlink:

$ $ echo "an example." > myfile
$ ln -s myfile myslink
$ ls myfile myhlink

使用stat检查前述文件:

$ stat my*
  File: `myfile'
  Size: 12          Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 11552       Links: 2
Access: (0664/-rw-rw-r--)  Uid: (  500/     wjm)   Gid: (  500/     wjm)
Access: 2016-08-10 03:59:54.421017669 +0800
Modify: 2016-08-10 03:59:54.421017669 +0800
Change: 2016-08-10 04:00:08.689000105 +0800
  File: `myhlink'
  Size: 12          Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 11552       Links: 2
Access: (0664/-rw-rw-r--)  Uid: (  500/     wjm)   Gid: (  500/     wjm)
Access: 2016-08-10 03:59:54.421017669 +0800
Modify: 2016-08-10 03:59:54.421017669 +0800
Change: 2016-08-10 04:00:08.689000105 +0800
  File: `myslink' -> `myfile'
  Size: 6           Blocks: 0          IO Block: 4096   symbolic link
Device: fd00h/64768d    Inode: 11553       Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (  500/     wjm)   Gid: (  500/     wjm)
Access: 2016-08-10 04:00:03.784997923 +0800
Modify: 2016-08-10 04:00:03.784997923 +0800
Change: 2016-08-10 04:00:03.784997923 +0800

仔细观察myfile和myhlink,发现它们指向同一个inode(inode号同为11552)。硬链接数(Links字段)同为2,这表示有两个目录项指向该inode,每增加一个硬链接Links字段值就会增加1。而myslink文件,我们发现它的inode号与前两个不同,其访问权限为0777。我们删除myhlink这个硬链接,看看会出现什么变化?这次我们用ls -il命令来查看:

$ rm myfile

$ ll -li
total 4
11552 -rw-rw-r-- 1 wjm wjm 12 Aug 10 03:59 myhlink
11553 lrwxrwxrwx 1 wjm wjm  6 Aug 10 04:00 myslink -> myfile

$ cat myhlink
an example.

$ cat myslink
cat: myslink: No such file or directory

ls命令的-i选项也可以输出文件的inode号。输出信息的第三列为硬链接数,我们发现删除了myfile文件后,myhlink的硬链接数已经由2变为1了,但是原myfile文件的数据依然可以通过myhlink这个硬链接访问,因为硬链接是通过文件的inode号来访问文件数据的。然而通过myslink软链接却无法再访问原myfile文件的数据了,因为软链接实质上是一个指向目标文件的全路径,这个路径中任何一个环节断裂,都会使这个软链接失效。

追随链接

自从了软连接,当你要备份、复制或者移动目录或者文件时候,会出现是否要“追随链接”的问题。如果是,则会复制链接所指向的对象;如果不是,则仅仅操作链接本身。

通常如tar或cp之类的命令工具会给出是否追随链接的选项。如cp,你可以使用-L选项表示追随链接(复制链接所指向的目标),或者用-P表示不追随链接(复制链接本身)。如下例:

$ mkdir dir1
$ ln -s /tmp/a.txt dir1/slink
$ cp -rL dir1 dir2
$ ls -l dir2
total 0
-rw-rw-r-- 1 wjm wjm 0 Aug  6 17:02 slink

这里我们在dir1目录下创建了一个软链接,当用-L选项将其复制到dir2目录下时,我们看到dir2目录下的slink现在成为一个普通文件。如果使用-P选项(保存链接)复制,则复制后的文件依然是一个软链接:

$ cp -rP dir1 dir3
$ ls -l dir3
total 0
lrwxrwxrwx 1 wjm wjm 10 Aug  6 17:07 slink -> /tmp/a.txt

假如没有明确指定-L或者-P选项,则cp的默认行为将随版本而定。

目录的硬链接

前文提到过,无法对一个目录创建硬链接。但其实目录是存在硬链接的,只是这个硬链接是系统自动创建的,而我们不能手动创建。当我们用mkdir创建一个空目录时,会发现这个目录的硬链接数为2,例如:

$ ls -dl ~
drwx------. 6 wjm wjm 4096 Aug 10 04:25 /home/wjm

$ cd ~
$ mkdir mydir

$ ls -dli ~
8605 drwx------. 7 wjm wjm 4096 Aug 10 04:25 /home/wjm

$ ls -dli mydir
11556 drwxrwxr-x 2 wjm wjm 4096 Aug 10 04:25 mydir

原先/home/wjm目录的硬链接数量为6,当在/home/wjm下创建了一个空目录mydir后,它的硬链接数量变成了7,而这个空目录mydir的硬链接数为2。这是为什么呢?原因是任何一个目录下,都有两个隐藏的硬链接:

ls -ali mydir
total 8
11556 drwxrwxr-x  2 wjm wjm 4096 Aug 10 04:25 .
 8605 drwx------. 7 wjm wjm 4096 Aug 10 04:25 ..

我们看到mydir目录下有两个隐藏的硬链接,使用ls的-a选项才能使其列出来。其中一个硬链接是“.”,指向的inode号为11556,就是mydir这个目录本身的inode号;另一个是“..”,通过inode号我们发现它指向了其父目录/home/wjm。因此,当创建了空目录mydir后,mydir的硬链接数为2,而其父目录的硬链接数加1。所以一个目录的硬链接数=其子目录数+2。

这种硬链接是系统自动为我们创建的,而当你试图手动创建一个指向目录的硬链接时,系统一定会报错阻止你这样做。为什么呢?

其实在UNIX操作系统的历史上,对目录创建硬链接曾经是允许的。但人们发现,这样做会出现很多问题,尤其是一些对目录树进行遍历操作的如fsck、find等命令无法正确执行。在《Unix高级环境编程》中提到作者Steven在自己的系统上做过实验,结果是:创建目录硬链接后,文件系统变得错误百出。因为这样做会破坏文件系统的树形结构,可能会使目录之间出现环。例如:

$ ln ~ ~/mydir/myhdir_link
ln: `/home/wjm': hard link not allowed for directory

$ ln -s ~ ~/mydir/myhdir_link

这里第一条命令我们试图在mydir目录下创建一个硬链接指向其父目录,然而失败了。因为这使得/home/wjm和/home/wjm/mydir两个目录之间形成一个环,我们无法再区分这两者谁是父目录谁是子目录了。然而第二条命令创建一个指向其父目录的软链接却可以成功,难道这样不是同样形成了一个环吗?

为什么软链接可以指向目录而硬链接不行呢?根本原因在于软链接实质上是一个文件,而硬链接实质上是一个目录项(dentry)。在linux系统中,每个文件(目录也是文件,软链接也是文件)都对应着一个inode结构,其中inode数据结构中包含了文件类型(目录,普通文件,符号连接文件等等)的信息,也就是说操作系统在遍历目录时可以判断出符号连接。既然可以判断出符号连接当然就可以采取一些措施来防范进入死循环了,系统在连续遇到8个符号连接后就停止遍历,这就是为什么对目录符号连接不会进入死循环的原因了。而“硬链接”本质上是“目录项”的同义词。当一个目标第一次被创建,就会为它创建一个目录项,这其实就是硬链接。大多数人常常把“硬链接”联想成为一个已有的对象创建一个额外的目录项,但其实是原来的目录项没有任何特殊,所有的硬链接都是平等的,所以Linux内核没有方法能识别出哪个是“原文件”哪个是“硬链接”。这样对于由于目录硬链接而形成的环就无法进行合适的处理。

但是根目录是一个特例。我们观察:

$ ls -dli /
2 dr-xr-xr-x. 22 root root 4096 Aug 10 00:50 /


$ ls -ali /
total 102
     2 dr-xr-xr-x. 22 root root  4096 Aug 10 00:50 .
     2 dr-xr-xr-x. 22 root root  4096 Aug 10 00:50 ..
... ...

可见这里根目录的inode号为2,而且根目录下的指向其父目录的隐藏硬链接(..)也指向了自身。

相关文章

最新评论