What is the difference between a symbolic link and a hard link?
最近有人在面试时问我这个问题。我诚实地说,我知道一个符号链接的行为方式和如何创建一个,但不理解硬链接的使用以及它与符号链接的区别。
在文件系统下,文件由inode表示(或者它是多个inode不确定)
文件系统中的文件基本上是指向inode的链接。然后,一个硬链接只创建一个链接到同一个底层inode的文件。
当您删除一个文件时,它会删除到基础inode的一个链接。只有当指向inode的所有链接都已删除时,inode才会被删除(或可删除/可重写)。
符号链接是指向文件系统中其他名称的链接。
一旦建立了硬链接,链接就指向inode。删除重命名或移动原始文件不会影响硬链接,因为它链接到基础inode。对inode上数据的任何更改都会反映在引用该inode的所有文件中。
注意:硬链接仅在同一文件系统中有效。符号链接可以跨越文件系统,因为它们只是另一个文件的名称。
使用任何Linux(ish)控制台都可以获得一些不错的直觉。
创建两个文件:
1 | $ touch foo; touch bar |
在其中输入一些数据:
1 2 | $ echo"Cat"> foo $ echo"Dog"> bar |
(实际上,我可以首先使用echo,因为它会创建不存在的文件…但别介意。)
如预期:
1 2 3 | $cat foo; cat bar Cat Dog |
让我们创建硬链接和软链接:
1 2 | $ ln foo foo-hard $ ln -s bar bar-soft |
让我们看看刚才发生了什么:
1 2 3 4 5 6 | $ ls -l foo foo-hard bar bar-soft -> bar |
更改foo的名称并不重要:
1 2 3 | $ mv foo foo-new $ cat foo-hard Cat |
foo硬指向文件的inode、内容,但没有更改。
1 2 3 4 5 | $ mv bar bar-new $ ls bar-soft bar-soft $ cat bar-soft cat: bar-soft: No such file or directory |
找不到文件的内容,因为软链接指向已更改的名称,而不是指向内容。
同样,如果删除
俗话说,一幅画胜过千言万语。以下是我对它的想象:
下面是我们如何得到这张图片:
在文件系统中创建一个名称
1 | $ echo 'Hello, World!' > myfile.txt |
创建一个指向文件
1 | $ ln myfile.txt my-hard-link |
创建一个到文件
1 | $ ln -s myfile.txt my-soft-link |
看看如果删除(或移动)
在移动原始文件时,硬链接非常有用。例如,将文件从/bin移到/usr/bin或移到/usr/local/bin。任何指向/bin中文件的符号链接都会被破坏,但是直接指向文件inode的硬链接并不重要。
硬链接可能占用较少的磁盘空间,因为它们只占用一个目录条目,而symlink需要自己的inode来存储它指向的名称。
硬链接也需要较少的时间来解决-符号链接可以指向符号链接目录中的其他符号链接。其中一些可能在NFS或其他高延迟文件系统上,因此可能导致需要解决的网络流量。硬链接始终在同一个文件系统上,总是在一次查找中解决,并且从不涉及网络延迟(如果它是NFS文件系统上的硬链接,则由NFS服务器进行解决,并且对客户端系统不可见)。有时候这很重要。不适合我,但我可以想象高性能系统在其中可能很重要。
我还认为mmap(2)甚至open(2)使用与硬链接相同的功能来保持文件的inode活动,这样即使文件被取消链接(2),inode仍然允许进程继续访问,并且只有当进程关闭时,文件才会真正消失。这允许更安全的临时文件(如果你能自动打开和断开链接,可能有一个我不记得的POSIX API,那么你真的有一个安全的临时文件),在那里你可以读/写你的数据,而没有任何人能够访问它。在/proc给每个人提供查看文件描述符的能力之前,这是正确的,但这是另一回事。
说到这一点,恢复一个在进程A中打开但在文件系统上未链接的文件需要使用硬链接重新创建inode链接,这样当打开该文件的进程关闭或关闭时,该文件不会消失。
查看硬链接和符号链接之间区别的一个简单方法是通过一个简单的示例。指向文件的硬链接将指向存储文件的位置或该文件的inode。符号链接将指向实际文件本身。
因此,如果我们有一个名为"a"的文件,并创建一个硬链接"b"和一个符号链接"c",它们都指的是文件"a":
1 2 3 | echo"111"> a ln a b ln -s a c |
"A"、"B"和"C"的输出为:
1 2 3 | cat a --> 111 cat b --> 111 cat c --> 111 |
现在让我们删除文件"a",看看"a"、"b"和"c"的输出会发生什么情况:
1 2 3 4 | 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,inode将继续存储属于"a"的任何内容,直到不再有硬链接指向它为止。
软链接:
软文件或符号文件更像是对原始文件的快捷方式……如果删除原始文件,则快捷方式将失败,如果只删除快捷方式,则原始文件不会发生任何变化。
软链接语法:
输出:
证明:
删除链接:
注意:如果您愿意,您的软链接可以工作,即使从当前目录移动到其他地方。请确保在创建软链接时提供绝对路径而不是相对路径。即(从/root/user/target_文件开始,而不是从/target_文件开始)
硬链接:
硬链接更多的是一个镜像副本或同一文件的多个路径。对文件1执行一些操作,它将出现在文件2中。删除一个仍保持另一个正常。
只有在删除了所有(硬)链接或指向(同一文件)inode的所有路径时,才会删除inode(或文件)。
一旦建立了硬链接,链接就拥有原始文件的inode。删除重命名或移动原始文件不会影响硬链接,因为它链接到基础inode。对inode上数据的任何更改都会反映在引用该inode的所有文件中。
硬链接语法:
输出:将使用与targetfile相同的inode编号创建名为link的文件。
证明:
删除链接:
注意:符号链接可以跨越文件系统,因为它们只是另一个文件的名称。而硬链接只在同一个文件系统中有效。
符号链接具有某些功能。缺少硬链接:
- 硬链接指向文件内容。当软链接指向文件名。
- 硬链接的大小是内容的大小,而软链接的大小是具有文件名大小。
- 硬链接共享相同的inode。软链接不能。
- 硬链接不能跨文件系统。软链接。
你很快就会知道符号链接指向什么地方链接,您需要浏览整个文件系统以查找文件共享同一个inode。
# find / -inum 517333
1
2/home/bobbin/sync.sh
/root/synchro硬链接不能指向目录。
硬链接有两个限制:
- 目录不能硬链接。Linux不允许这样做来维护目录的非循环树结构。
- 无法跨文件系统创建硬链接。两个文件都必须在同一个文件系统上,因为不同的文件系统具有不同的独立inode表(不同文件系统上的两个文件,但具有相同inode编号的文件将不同)。
符号链接链接到路径名。这可以在系统的文件树中的任何位置,甚至在创建链接时都不必存在。目标路径可以是相对路径或绝对路径。
硬链接是指向inode的附加指针,这意味着它们只能存在于与目标相同的卷上。指向文件的其他硬链接与用于引用文件的"原始"名称不可区分。
我会指给你维基百科:
- 符号链接
- 硬链接
几点:
- 与硬链接不同,symlinks可以跨文件系统(大多数情况下)。
- 符号链接可以指向目录。
- 硬链接指向一个文件,使您能够用多个名称引用同一个文件。
- 只要至少有一个链接,数据仍然可用。
进行增量备份时,硬链接非常有用。例如,请参见rsnapshot。其想法是使用硬链接进行复制:
- 将备份号n复制到n+1
- 将备份n-1复制到n
- …
- 将备份0复制到备份1
- 使用任何更改的文件更新备份0。
除了您所做的任何更改外,新备份不会占用任何额外的空间,因为所有增量备份都将指向同一组未更改的inode文件。
我补充了尼克的问题:硬链接何时有用或必要?我想到的唯一一个应用程序是在chroooted环境中提供系统文件的副本,在这个应用程序中,符号链接不能完成这项工作。
硬链接和软链接可以很容易地用这个图像来解释。
你认为一个普通的"文件"实际上是两个不同的东西:一个文件的数据和一个目录条目。当您为一个文件创建硬链接时,实际上您创建了第二个目录条目,它引用了相同的数据。两个目录条目具有完全相同的功能;每个目录条目都可以用来打开文件进行读取。所以你没有"一个文件加一个硬链接",你有"两个目录条目的文件数据"。您所认为的删除文件实际上会删除一个目录条目,当数据的最后一个目录条目被删除时,数据本身也会被删除。对于只有一个目录条目的普通文件,删除目录条目将一如既往地删除数据。(打开文件时,操作系统会创建一个指向该文件的临时链接,因此即使删除所有目录条目,数据也会保留,但一旦关闭该文件,数据就会消失)。
例如,创建一个文件a.txt,一个硬链接b.txt,然后删除a.txt。创建.txt时,会创建一些数据和目录条目a.txt。创建硬链接时,会创建另一个目录条目b.txt,指向完全相同的数据。当您删除a.txt时,您仍然拥有所有数据和一个目录条目b.txt,就好像您首先创建了一个文件b.txt一样。
软链接只是一个(几乎)普通的文件,只是它不包含数据,而是另一个目录条目的路径。如果删除软链接引用的文件,则软链接将包含不再指向目录项的路径;该路径已被破坏。如果删除软链接,就像删除任何其他文件一样,它指向的文件不受影响。
也:
除上述所有答案外,查找硬链接和软链接文件的区别可以理解为:
我在当前目录中有一个文件
名为
名为
要查找软链接和硬链接,我们可以使用:
1 2 3 4 5 6 7 | $ find -L . -samefile f6 > ./f1 > ./f6 > ./f7 > ./t2/f2 > ./t2/f8 |
要仅查找硬链接,我们可以使用:
1 2 3 4 5 | $ find . -xdev -samefile f6 > ./f6 > ./f7 > ./t2/f8 |
由于硬链接可以在同一文件系统上创建,因此我们可以搜索所有硬链接,而不使用同一文件系统/装入点中使用的
因此,搜索硬链接比搜索软链接要快一些(如果我错了或不清楚,请纠正)。
简单地说,硬链接:就是在一个文件中添加一个新的名字,也就是说,一个文件可以同时有多个名字,所有的名字都相等,没有人喜欢,硬链接不是指复制文件的所有内容并生成新的文件,它只是创建一个可供选择的名字。
符号链接(symlink):是指向另一个文件的文件指针,如果符号链接指向某个现有文件,而该文件随后被删除,则符号链接将继续指向同一文件名,即使该文件名不再命名任何文件。
来自MSDN,符号链接
A symbolic link is a file-system object that points to another file system object. The object being pointed to is called the target.
Symbolic links are transparent to users; the links appear as normal
files or directories, and can be acted upon by the user or application
in exactly the same manner.Symbolic links are designed to aid in migration and application
compatibility with UNIX operating systems. Microsoft has implemented
its symbolic links to function just like UNIX links.Symbolic links can either be absolute or relative links. Absolute
links are links that specify each portion of the path name; relative
links are determined relative to where relative–link specifiers are in
a specified path
绝对符号链接示例
1 2 3 | X:"C:\alpha\beta\absLink\gamma\file" Link:"absLink" maps to"\\machineB\share" Modified Path:"\\machineB\share\gamma\file" |
相对符号链接示例
1 2 3 4 | X: C:\alpha\beta\link\gamma\file Link:"link" maps to"..\..\theta" Modified Path:"C:\alpha\beta\..\..\theta\gamma\file" Final Path:"C:\theta\gamma\file" |
硬链接
A hard link is the file system representation of a file by which
more than one path references a single file in the same volume.
要在Windows中创建硬链接,请导航到要创建链接的位置并输入以下命令:
1 | mklink /H Link_name target_path |
请注意,无论硬链接的创建顺序如何,您都可以删除任何顺序。此外,当
- 引用位于不同的本地驱动器中
- 参考包括网络驱动器。换句话说,其中一个引用是网络驱动器
- 要创建的硬链接与目标的路径相同
接合
NTFS支持另一种称为连接的链接类型。msdn定义如下:
A junction (also called a soft link) differs from a hard link in that the storage objects it references are separate directories, and a junction can link directories located on different local volumes on the same computer. Otherwise, junctions operate identically to hard links.
硬连接部分和连接部分的粗体部分显示了两者的基本区别。
命令要在Windows中创建连接,请导航到要创建链接的位置,然后输入:
1 | mklink /J link_name target_path |
目录项是链接结构:
1 2 3 4 | struct dentry{ ino_t ino; char name[256]; } |
ino是inode的编号,name是文件名,inode结构可能类似:
1 2 3 4 | struct inode{ link_t nlink; ... } |
例如,您创建一个文件/1,目录条目可能如下:
1 2 3 4 | struct dentry{ ino_t ino; /* such as 15 */ char name[256]; /*"1" */ } |
inode结构可能是:
1 2 3 4 | struct inode{ /* inode number 15 */ link_t nlink; /* nlink = 1 */ ... } |
然后创建一个硬链接(可能是/100),目录条目可能如下:
1 2 3 4 | struct dentry{ ino_t ino; /* 15 */ char name[256]; /* 100 */ } |
inode结构可能是:
1 2 3 4 | struct inode{ /* inode numebr 15 */ link_t nlink; /* nlink = 2 */ ... } |
然后创建到文件1的符号链接(可能是/200),目录条目可能如下:
1 2 3 4 | struct dentry{ ino_t ino; /* such as 16 */ char name[256]; /*"200" */ } |
inode结构可能是:
1 2 3 4 5 6 7 8 9 | 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 */ |
符号链接以类似于硬链接的方式为文件赋予另一个名称。但是,即使有剩余的符号链接,也可以删除文件。
我的2分用法:
软链接可用于缩短长路径名称,即:
1 | ln -s /long/folder/name/on/long/path/file.txt /short/file.txt |
对
硬链接可用于移动大文件:
1 2 3 | $ ls -lh /myapp/dev/ total 10G -rw-r--r-- 2 root root 10G May 22 12:09 application.bin |
即时复制到不同文件夹,可以移动或删除原始文件(在
我刚刚找到了一个简单的方法来理解常见场景中的硬链接,即软件安装。
有一天我下载了一个软件到
在这个答案中,当我说一个文件时,我指的是内存中的位置。
所有保存的数据都使用名为inode的数据结构存储在内存中,每个inode都有一个inode number。inode编号用于访问inode。到文件的所有硬链接可能具有不同的名称,但共享相同的inode编号。由于所有硬链接都具有相同的inodenumber(Inturn访问相同的inode),因此它们都指向到相同的物理内存。
符号链接是一种特殊类型的文件。由于它也是一个文件,因此它将有一个文件名和一个inode编号。如上所述,inode编号接受一个指向数据的inode。现在,使符号链接特殊的是,符号链接中的inode number访问那些指向另一个文件的"路径"的inode。更具体地说,inod符号链接中的e号接受指向另一个硬链接的inode。
当我们在GUI中移动、复制、删除文件时,我们使用的是文件的硬链接,而不是物理内存。当我们删除文件时,我们将删除文件的硬链接。我们没有清除物理内存。如果删除了所有指向文件的硬链接,则无法访问存储的数据,尽管它可能仍然存在于内存中。