链接的“软”与“硬”

前言

    类似Windows系统,Linux系统在进行文件管理时,也会引入链接概念。而链接又分为软链接和硬链接,两种链接适用于不同场合、不同用途,各有优缺点。在介绍软硬两种链接之前,需要先引入inode的概念。

Inode

    系统在管理文件时,为了有序寻址,会将元数据(metadata)和用户数据(userdata)分开存放。元数据是指文件各类附加属性,如ls –l命令中显示的文件类型、权限、属主属组、文件大小、修改时间以及文件名等信息;而用户数据是指真实的对用户有用的数据。Linux不同路径下可以创建相同文件名称的文件,对于计算机系统来说,识别二进制数字比直接的文件名更为快捷。所以Linux系统用不同的数字来标识不同的文件,而此数字就是inode号,即索引节点号(index node)。元数据中的inode才是系统识别文件的唯一标识符。

blob.png

查看inode相关的命令:ls –i 、 stat 、 df –i

[root@Hisen /]# ls -i
393219 bin  524290 home  917506 media 1048581 opt 131074 selinux 393217 tmp
  2 boot  786434 lib   12503 misc     1 proc 393220 srv      2 usr
  4 dev  262146 lib64  917507 mnt  1048578 root   1 sys      2 var
1179649 etc 11 lost+found  2507 net 131075 sbin 131099 testdir
[root@Hisen /]# stat bin/
File: `bin/'
Size: 4096          Blocks: 8     IO Block: 4096   directory
Device: fd00h/64768d     Inode: 393219   Links: 2
Access: (0555/dr-xr-xr-x)  Uid: (0/root)   Gid: (0/root)
Access: 2016-10-19 11:58:26.863958830 +0800
Modify: 2016-10-18 09:07:21.360998536 +0800
Change: 2016-10-18 09:07:21.360998536 +0800
[root@Hisen /]# df -i
Filesystem        Inodes   IUsed   IFree    IUse%    Mounted on
/dev/mapper/vg0-root   1310720   7105    1303615   1%      /
tmpfs           125596     1    125595   1%      /dev/shm
/dev/sda1         51200     38     51162   1%      /boot
/dev/mapper/vg0-usr    655360  100297     555063   16%      /usr
/dev/mapper/vg0-var   1310720    3150    1307570   1%      /var
/dev/sdb         1310720     12    1310708   1%      /mnt/cdrom

 

  一个节点是一个表项,其中包含有关文件信息的元数据,包括:

    文件类型

    权限

    UID

    GID

    硬链接数

    文件大小

    时间戳

    指针

    其他数据

blob.png

   简而言之,对于Linux系统来说,所有的目录映射都是文件之间的inode号映射。

   由于每个分区都有着自身的一套inode号,在执行类似于cp和mv的命令,会对目标文件的inode号有何影响?

cpinode

[root@Hisen ~]# cp  /Hisen/testfile1  /tmp/
[root@Hisen ~]# ll  -i  /Hisen/testfile1  /tmp/testfile1
917512 -rw-r--r-- 1 root root 0 Oct 19 12:51 /Hisen/testfile1
393361 -rw-r--r-- 1 root root 0 Oct 19 13:19 /tmp/testfile1

   cp命令复制文件的原理:分配一个空闲的inode号,在inode表中生成新条目在目录中创建一个目录项,将名称与inode编号关联拷贝数据生成新的文件。

mv和inode:

   ①如果mv命令的目标和源在相同的文件系统

[root@Hisen ~]# rm -rf /tmp/testfile1
[root@Hisen ~]# ll -i /Hisen/testfile1
917512 -rw-r--r-- 1 root root 0 Oct 19 12:51 /Hisen/testfile1
[root@Hisen ~]# mv /Hisen/testfile1 /tmp/
[root@Hisen ~]# ll -i /tmp/testfile1
917512 -rw-r--r-- 1 root root 0 Oct 19 12:51 /tmp/testfile1

  用新的文件名创建对应新的目录项,删除旧目录条目对应的旧的文件名,不影响inode表(除时间戳)或磁盘上的数据位置:没有数据被移动

   ②如果目标和源在一个不同的文件系统

   将sdb硬盘挂载至/mnt/cdrom下:

[root@Hisen ~]# mount
/dev/sdb on /mnt/cdrom type ext4 (rw)

   /Hisen/testfile1的原始inode:

[root@Hisen ~]# ll -i /Hisen/testfile1
917512 -rw-r--r-- 1 root root 0 Oct 19 12:51 /Hisen/testfile1

  /Hisen/testfile1移动至不同分区的/mnt/cdrom下:

[root@Hisen ~]# mv /Hisen/testfile1 /mnt/cdrom/
[root@Hisen ~]# ll -i /mnt/cdrom/testfile1 
12 -rw-r--r-- 1 root root 0 Oct 19 12:51 /mnt/cdrom/testfile1

rminode

  删除文件其实就是释放inode号,而之前的用户数据则依然保存在硬盘内部,只不过系统会将没有inode号的数据标记为空闲状态。 

硬链接

      如果用人来形容的话,inode号就相当于身份证号码,在同分区内唯一标识。而硬链接就相当于将我们重新取个名字,但在本质上,都是我们自己本身。

   命令:ln  filename  [linkname ]

  用ls –l命令可以查看当前文件的硬链接数:

[root@Hisen Hisen]# ll -di /Hisen/
917509  drwxr-xr-x  3  root  root  4096  Oct  19 13:35  /Hisen/

  其中数字3就代表当前目录的硬链接数。那么这3次硬链接又是从何而来?

  /Hisen/目录本身inode号: 

[root@Hisen ~]# ll -id /Hisen/
917509 drwxr-xr-x 3 root root 4096 Oct 19 13:35 /Hisen/

  /Hisen/目录下所有子文件inode信息:

[root@Hisen ~]# ll -ai /Hisen/
917509  drwxr-xr-x   3  root root   4096   Oct  19  13:35  .
     2  dr-xr-xr-x.  26  root root   524288  Oct  19  12:50  ..
917511  drwxr-xr-x   2  root root   4096    Oct  19  12:52  testdir1

  子目录/Hisen/testdir1/目录下子文件inode信息:

[root@Hisen ~]# ll -ai /Hisen/testdir1/
917511  drwxr-xr-x  2  root  root  4096  Oct  19  12:52  .
917509  drwxr-xr-x  3  root  root  4096  Oct  19  13:35  ..
917513  -rw-r--r--   1  root  root     0  Oct  19  12:52  testfile2

  可以看出:/Hisen/自身目录下有·和··的隐藏目录,而·目录的inode号跟自身相同,··目录的inode号跟父目录相同,而/Hisen/testdir1/目录下··的inode号又跟/Hisen/目录相同。

    因此默认的目录下都会出现·和··两个隐藏目录项,其中·代表当前目录的硬链接,··代表父目录对当前目录的硬链接,所以每个目录文件都至少有2次硬链接。由于当前目录的子目录也会对父目录进行硬链接,所以每个目录的硬链接数等于2加上子目录数。而在/Hisen/目录下,有一个testdir1的目录文件,所以硬链接数为3

    既然我们知道目录的硬链接数从何而来,那么接下来再看看文件的硬链接数吧。

    将/Hisen/testdir1/下的testfile2硬链接至/tmp/下,链接名为link01:

[root@Hisen ~]# ln   /Hisen/testdir1/testfile2  /tmp/link01
[root@Hisen ~]# ll -i /Hisen/testdir1/testfile2 /tmp/link01
917513 -rw-r--r-- 2 root root 6 Oct 19 14:30 /Hisen/testdir1/testfile2
917513 -rw-r--r-- 2 root root 6 Oct 19 14:30 /tmp/link01

  上例可知硬链接一次文件,该文件的硬链接次数增加1。

  /Hisen/testdir1/testfile2文件中只保存‘Hisen’五个英文字符,接下来我们删除/Hisen/testdir1/testfile2,看看link01文件是否能正常访问。

[root@Hisen ~]# rm -rf /Hisen/testdir1/testfile2
[root@Hisen ~]# cat /tmp/link01
Hisen

  由上可知,硬链接映射同一个inode号,删除其中一个文件名,并不影响其他文件名的使用。多个硬链接名之间并无任何依赖关系存在。

blob.png

如果将文件跨分区进行硬链接,会出现设备结果?

[root@Hisen ~]# ln /Hisen/testdir1/testfile2 /mnt/cdrom/
ln:creating hard link `/mnt/cdrom/testfile2' => `/Hisen/testdir1/testfile2': Invalid cross-device link

上面例子提示,无法跨设备进行硬链接。是因为,每个分区都会有自己的inode号,不同的分区下相同的inode号很可能有不同的用途。

关于路径,硬链接既可以使用当前绝对路径(见上例),也可以使用相对路径。其中相对路径又分为:相对于当前目录和相对于链接目标文件的路径。

相对于当前路径的硬链接:

[root@Hisen testdir1]# ln testfile2 /tmp/link02
[root@Hisen testdir1]# ll -i testfile2 /tmp/link02 
917513 -rw-r--r-- 2 root root 6 Oct 19 14:30 testfile2
917513 -rw-r--r-- 2 root root 6 Oct 19 14:30 /tmp/link02

相对于链接目标文件的硬链接:

[root@Hisen ~]# ln  ../Hisen/testdir1/testfile2 /tmp/link03
[root@Hisen ~]# ll -i /Hisen/testdir1/testfile2 /tmp/link03
917513 -rw-r--r-- 3 root root 6 Oct 19 14:30 /Hisen/testdir1/testfile2
917513 -rw-r--r-- 3 root root 6 Oct 19 14:30 /tmp/link03

软链接

  软链接就相当于windows系统的快捷方式,它对被链接文件的依赖性非常强。软链接是一个全新的文件,被分配了一个不同于被链接文件的inode号,也就相当于软链接文件中保存的就是被链接文件的路径。如果按照存储中的路径找不到跟被链接文件相同文件名的文件,那么此软链接将会失效。言外之意就是,软链接并不关心被链接文件的具体内容,只要按照路径查找能匹配到相同文件名就好。软链接的优势在于它能跨分区跨设备甚至跨网络。

  命令:ln  -s  filename  [linkname]

[root@Hisen ~]# ln -s /Hisen/testdir1/testfile2 /tmp/link04
[root@Hisen ~]# ll -i /Hisen/testdir1/testfile2 /tmp/link04
917513 -rw-r--r-- 1 root root  6 Oct 19 14:30 /Hisen/testdir1/testfile2
393362 lrwxrwxrwx 1 root root 25 Oct 19 15:16 /tmp/link04 -> /Hisen/testdir1/testfile2

由上例可看出,软链接与实际文件的差别挺大的。/tmp/link04文件有25字节大小,具体内容为真实文件的路径,不信自己数一数。

将/Hisen/testdir1/testfile2文件删除后,软链接就呈现失效的状态。

blob.png

那么在/Hisen/testdir1/下新建一个文件名为testfile2的文件会有什么效果呢?

blob.png

软链接又恢复正常状态,印证了软链接并不关心文件里的具体内容。

另外,硬链接不能针对目录,那么软链接能否针对目录呢?

blob.png

上图已经证实,软链接是可以针对于目录做链接。

我们已经知道,硬链接是无法跨设备跨分区的,那么软链接跨分区的效果如何?

blob.png

  正如所料到的那样,一切正常,证明软链接是可以跨设备跨分区的。

  接下来,关于链接路径的写法,软链接和硬链接有着比较大的区别:

  ①当前目录下:

  blob.png

  ②绝对路径:

  blob.png

  ③相对于被链接文件路径的相对路径:

    blob.png

  综上,软链接支持绝对路径和被链接文件路径相对的路径链接,但是由于在开发环境中考虑到可移植性,最好写成相对路径

总结

  通过上面两节对软链接和硬链接的介绍后,相信区别已经显而易见了。不过还是需要好好的总结一下:

        1、命令格式:

硬链接:ln  filename  [linkname ]

软链接ln  -s  filename  [linkname]

2、inode

硬链接:与被链接目标文件相同,创建时链接数递增;

软链接:与被链接目标文件不同,创建时目标文件inode引用计数不变。

3、依赖性:

硬链接:链接之后,与原名称无关,直接指向真实的数据。删除原文件名,不影响新文件名使用数据;

软链接:链接之后,需要能在保存的路径下匹配到相同的文件名。删除原文件名,则链接失效。

4、存储数据:

硬链接:直接指向真实的数据,相同的inode号;

软链接:存储的是被链接文件的路径。

5、跨设备跨分区:

硬链接:不可以;

软链接:可以。

6、链接路径:

硬链接:可当前、可绝对、可相对被链接文件路径;

软链接:不可当前、可绝对,可相对被链接文件路径。

7、链接对象:

硬链接:可文件、不可目录;

软链接:可文件、可目录。


原创文章,作者:Hisen,如若转载,请注明出处:http://www.178linux.com/53158

(0)
HisenHisen
上一篇 2016-10-20
下一篇 2016-10-20

相关推荐

  • 【听说要写一篇文章,我觉得标题比较长的人一定特别帅。】

    我叫小问。 计划是学好马哥所教授的知识。 目标是找到一份好工作!

    Linux干货 2016-10-23
  • keepalived高可用实例

    1、keepalived单实例 1)实验环境为VMware虚拟机,两台centos7.2,主机1IP地址为10.1.252.55,主机2IP地址为10.1.252.34,虚拟路由IP为10.1.252.246, 2)确保iptables和selinux不影响实验 (1)确保两台主机的时间同步 [root@localhost ~]# vim…

    Linux干货 2016-11-01
  • N26-上海-莫言

    持续更新…

    Linux干货 2016-12-26
  • HSRP vs VRRP

    HSRP:(Hot Standby Router Protocol)-热备份路由协议 是cisco平台一种特有的技术,是cisco的私有协议。 VRRP:(Virtual Router Redundancy Protocol)-虚拟路由冗余协议 是国际标准,由IETF提出的解决局域网中配置静态网关出现单点失效现象的路由协议。 ----------------…

    Linux干货 2016-10-19
  • 程序包管理之YUM解析

    前言:    yum是rpm的前端程序,用来解决软件包相关依赖性,可以在多个库之间定位软件包,如果直接使用rpm直接安装程序包也可以,但是需要自己手工解决程序包依赖性的问题,可能程序包的依赖性非常复杂,那么直接使用rpm安庄,就会非常麻烦,而使用YUM安装就会自动解决依赖性的问题。大大简化了安装过程。  YUM客户端配置文件: …

    Linux干货 2016-08-24
  • 第九周作业

    1、写一个脚本,判断当前系统上所有用户的shell是否为可登录shell(即用户的shell不是/sbin/nologin);分别这两类用户的个数;通过字符串比较来实现; #!/bin/bash LOGIN_USER=0 NOLOGIN_USER=0 for SHELLUSER in $(cat /etc/passwd | cut -d : -f 7);do…

    Linux干货 2017-07-03