最近我在一次工作面试中被问到这个问题。我诚实地说,我知道符号链接的行为和如何创建一个,但不了解硬链接的使用,以及它与符号链接的区别。


当前回答

另外:

硬链接的读取性能优于符号链接(微性能) 符号链接可以被复制,版本控制,等等。换句话说,它们是一个实际的文件。另一方面,硬链接的级别略低,您会发现,与符号链接相比,提供将硬链接作为硬链接而不是普通文件处理的工具较少

其他回答

我对使用的两点看法:

软链接可以用来缩短长路径名,例如:

ln -s /long/folder/name/on/long/path/file.txt /short/file.txt

对/short/file.txt所做的更改将应用于原始文件。

硬链接可以用来移动大文件:

$ ls -lh /myapp/dev/
total 10G
-rw-r--r-- 2 root root 10G May 22 12:09 application.bin

ln /myapp/dev/application.bin /myapp/prd/application.bin

即时复制到不同的文件夹,原始文件(在/myapp/dev上)可以移动或删除,而不会触及/myapp/prd上的文件

通过一个简单的例子可以看出硬链接和符号链接之间的区别。指向文件的硬链接将指向存储文件的位置,或者指向该文件的inode。符号链接将指向实际文件本身。

因此,如果我们有一个名为“a”的文件,并创建一个硬链接“b”和一个符号链接“c”,它们都指向文件“a”:

echo "111" > a
ln a b
ln -s a c

“a”,“b”和“c”的输出将是:

cat a --> 111
cat b --> 111
cat c --> 111

现在让我们删除文件“a”,看看“a”,“b”和“c”的输出会发生什么:

rm a
cat a --> No such file or directory
cat b --> 111
cat c --> No such file or directory

到底发生了什么?

因为文件“c”指向文件“a”本身,如果文件“a”被删除,那么文件“c”将没有什么可指向的,实际上它也被删除了。

但是,文件“b”指向文件“a”的存储位置或inode。因此,如果文件“a”被删除,那么它将不再指向inode,但由于文件“b”被删除,inode将继续存储属于“a”的任何内容,直到不再有硬链接指向它。

一个目录条目链接一个结构:

struct dentry{
    ino_t ino;
    char  name[256];
}

ino是inode的编号,name是文件名,inode结构可能是这样的:

struct inode{
      link_t nlink; 
      ...
}

例如,你创建一个文件/1,目录条目可能是这样的:

struct dentry{
     ino_t ino; /* such as 15 */
     char  name[256]; /* "1" */
} 

inode结构可能是这样的:

   struct inode{ /* inode number 15 */
         link_t nlink; /* nlink = 1 */
         ...
    }

然后你创建一个硬链接(可能是/100),目录条目可能是这样的:

  struct dentry{
     ino_t ino; /* 15 */
     char  name[256]; /* 100 */
  }

inode结构可能是这样的:

   struct inode{ /* inode numebr 15 */
         link_t nlink; /* nlink = 2 */
         ...
    }

然后你创建一个符号链接(可能是/200)到文件1,目录条目可能是这样的:

  struct dentry{
        ino_t ino; /* such as 16 */
        char  name[256]; /* "200" */
  }

inode结构可能是这样的:

   struct inode{ /* inode number 15 */ 
         link_t nlink; /* nlink = 2 */
         ...
    }

   struct inode{ /* inode number 16 */
         link_t nlink; /* nlink = 1 */
         ...
    } /* the data of inode 16 maybe /1 or 1 */

一些例子可能会有所帮助。

创建两个包含数据的文件:

$ printf Cat > foo
$ printf Dog > bar

创建一个硬链接和软链接(又名符号链接):

$ ln foo foo-hard
$ ln -s bar bar-soft

通过增加大小以长格式列出目录内容:

ls -lrS
lrwxr-xr-x   1 user  staff        3  3 Apr 15:25 bar-soft -> bar
-rw-r--r--   2 user  staff        4  3 Apr 15:25 foo-hard
-rw-r--r--   2 user  staff        4  3 Apr 15:25 foo
-rw-r--r--   1 user  staff        4  3 Apr 15:25 bar

这告诉我们

1st column: the file mode for the soft and hard links differ soft link: lrwxr-xr-x filetype: l = symbolic link owner permissions: rwx = readable, writable, executable group permissions: r-x = readable, not writable, executable other permissions: r-x = readable, not writable, executable hard link: -rw-r--r-- filetype: - = regular file owner permissions: rw- = readable, writable, not executable group permissions: r-- = readable, not writable, not executable other permissions: r-- = readable, not writable, not executable 2nd column: number of links is higher for the hard linked files 5th column: the size of the soft link is smaller, because it's a reference as opposed to a copy last column: the symbolic link shows the linked-to file via ->

更改foo的文件名不会影响foo-hard:

$ mv foo foo-new
$ cat foo-hard
Cat

更改foo的内容反映在foo-hard中:

$ printf Dog >> foo
$ cat foo-hard
CatDog

像foo-hard这样的硬链接指向文件的inode(内容)。

这不是像bar-soft这样的软链接的情况:

$ mv bar bar-new
$ ls bar-soft
bar-soft
$ cat bar-soft  
cat: bar-soft: No such file or directory

无法找到文件的内容,因为软链接指向已更改的名称,而不是指向内容。

同样地,如果foo被删除,foo-hard仍然保存内容;如果bar被删除,bar-soft只是一个指向不存在文件的链接。

在文件系统下面,文件由inode表示。(或者是多个索引节点?不确定。)

文件系统中的文件基本上是一个到inode的链接。 因此,硬链接只是创建另一个文件,该文件具有指向相同底层inode的链接。

当您删除一个文件时,它会删除到底层inode的一个链接。只有当到inode的所有链接都被删除时,inode才会被删除(或可删除/可覆盖)。

符号链接是指向文件系统中另一个名称的链接。

一旦建立了硬链接,链接就指向inode。删除、重命名或移动原始文件不会影响硬链接,因为它链接到底层inode。对inode上数据的任何更改都反映在引用该inode的所有文件中。

注意:硬链接只在同一个文件系统内有效。符号链接可以跨文件系统,因为它们只是另一个文件的名称。