linux中的硬链接和软链接-symbolic link and hard link in Linux
Inode 和 Inode number
在linux的世界中,一切皆文件。每创建一个文件(包括文件夹)都会创建一个Inode和分配一个Inode Number与之对应。Inode Number是在整个文件系统是唯一,可以唯一标记一个Inode,在linux中就是通过将文件名与Inode Number的对应关系,查找对应的Inode和读取文件的。
Inode的结构
下图是一个文件File.txt的Inode结构:
Inode中Meta Data
Meta Data是一个保存所指向文件的元数据,其中并不包括文件名,文件名被存储在所在的文件夹的对应的文件中,Meta data包括以下内容:
- 文件的类型: 文件, 文件夹, pipe 等.
- 文件权限: read, write, execute
- Link count: 表示有多少的文件名或硬链接指向这个Inode
- User ID: 拥有这个文件的用户ID
- Group ID: User ID所在的组
- Size of file: 文件大小
- Time stamp: 记录读取文件,修改文件,或者Inode属性改变的时间
- 其他属性等
Inode中的指针
除了文件的元数据,Inode还保存着15个指向文件的指针。前12个指针直接指向文件的数据,后3个指针分别是多层指针树结构的入口,拖过这些指针就可以读取到文件的数据块。前12个指针直接指向文件数据,对于小文件足够用了,而后面的3个指针则提高了读取大文件的能力。通过这样的设计可以提高文件读取效率。
下图是一个根目录的Inode结构,Inode指向的文件是一个file entry,包含了根目录下的所有文件和它对应的Inode Number。
使用ls命令和stat查看Inode信息
使用ls
命令加上-i
会在显示文件指向Inode的Inode Number
-i, --inode print the index number of each file
如下图所示,第一列就是对应的Inode Number,最后一列是文件名。这两列的信息来自于根目录这个文件的file entry。其他的来自于对应Inode的元数据。
使用stat
命令查看文件名指向的Inode的信息
root@c73df814e7b2:/# echo 'hello' > file.txt
root@c73df814e7b2:/# ls -ali
total 96
90932 drwxr-xr-x 1 root root 4096 Apr 15 16:59 .
90932 drwxr-xr-x 1 root root 4096 Apr 15 16:59 ..
90930 -rwxr-xr-x 1 root root 0 Apr 13 16:40 .dockerenv
90782 drwxr-xr-x 1 root root 4096 Apr 13 16:55 bin
90922 drwxr-xr-x 1 root root 4096 Apr 13 16:55 etc
90964 -rw-r--r-- 1 root root 6 Apr 15 16:59 file.txt
root@c73df814e7b2:/# stat file.txt
File: file.txt
Size: 6 Blocks: 8 IO Block: 4096 regular file
Device: 7bh/123d Inode: 90964 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2021-04-15 16:59:22.550000000 +0000
Modify: 2021-04-15 16:59:22.550000000 +0000
Change: 2021-04-15 16:59:22.550000000 +0000
Birth: -
root@c73df814e7b2:/#
读取一个文件的流程
理解文件与Inode,Inode Number的关系之后,来看看读取/foo/File.txt
的流程:
- 根据固定值读取
/
的Inode信息 - 根据Inode指针读取
/
的数据,获取目录下的文件名为foo的文件对应的Inode Number - 根据foo的Inode Number读取目录下的所以文件,找到File.txt文件对应Inode Number
- 根据File.txt的Inode Number根据Inode上的指针读取文件
软连接
创建一个hello.txt
文件,然后使用ln -s link_hello /home/liu/foo/hello.txt
创建一个指向hello.txt
的软连接。
从上图可以看到hello.txt
和软连接的Inode Number是不一样的。源文件一旦移动,删除或者重新命名都会使软连接失效。
软连接是固定指向一个目录下的文件名,软连接指向的文件如下图:link_hello指向了一个固定目录里面的固定名字的文件,一旦文件名修改,文件被移动到别的目录或者文件被删除了(文件夹里面保存的文件名与Indoe Number的映射关系也会别删除),软连接到指定的目录找这个文件就找不到了,这时候这个软连接就变成的了一个坏连接。
硬链接
如下图创建一个指向hello.txt
的硬链接hlink
,他们的Inode Number 是一样的,说明文件名hello.txt
和hlink
都指向了同一个Inode,第三列的值(link count)变成了2,表示有两个文件名指向的这个文件。
下图是创建硬链接的过程,实质上创建一个硬链接就是在目录上加上一个硬链接名和它指向文件的Inode Number,这硬链接和上面的文件名本质上是一样的。同一个文件,可以有多个文件名,对其中的一个文件名进行删除操作时,linux将link count减一,当link count减少为0,linux将删除这个文件。
删除hello.txt
,可以看到linkcount变成了1,hlink
指向的Inode Nuber没变,指向的是同一个文件。
软硬链接的区别
从上面的解释可知,软连接指向的是目录下的文件名,硬链接指向的是目标文件的Inode。删除原文件,软连接变成坏链接,硬链接仍然可用。删除软连接,不会对文件有任何影响,而删除硬链接,要看linkcount,如果没有其硬链接引用它,便会删除文件。
下面是软硬链接的其他区别: