Unix下的硬连接和软连接文件

来源:互联网 发布:淘宝等级最高的店铺 编辑:程序博客网 时间:2024/05/17 07:10

发现创建的符号链接删除不了,搜索才知道删除符号连接时文件名后面不能后缀一个/。比如:
[whb@jcwkyl test]$ ln -s ~whb
[whb@jcwkyl test]$ ls
whb
[whb@jcwkyl test]$ rm whb/
rm: cannot remove `whb/': Not a directory
[whb@jcwkyl test]$ rm -f whb/
rm: cannot remove `whb/': Not a directory
[whb@jcwkyl test]$ rm whb
[whb@jcwkyl test]$ ls

把硬连接和符号连接的概念再复习一下:
Unix下每个文件都有一个与之关联的数据结构用来描述该文件的信息,这个数据结构就是inode。
例如,创建一个文件:
[whb@jcwkyl test]$ ls
[whb@jcwkyl test]$ cat > testfile <<EOF
> This is just an example!
> EOF

testfile这个文件名就指向了一个inode数据结构,可以用stat命令查看这个inode的信息:
[whb@jcwkyl test]$ stat testfile 
  File: `testfile'
  Size: 25              Blocks: 8          IO Block: 4096   regular file
Device: 802h/2050d      Inode: 9306116     Links: 1
Access: (0664/-rw-rw-r--)  Uid: (  500/     whb)   Gid: (  500/     whb)
Access: 2010-01-06 16:16:27.000000000 +0800
Modify: 2010-01-06 16:16:27.000000000 +0800
Change: 2010-01-06 16:16:27.000000000 +0800

文件testfile的inode号是9306116。在GNU C中,可以用stat, fstat, lstat三个函数查看一个文件的信息,它们的区别在于如果查看的是一个符号连接文件,则lstat显示的是符号连接文件本身的信息,而fstat显示的是符号连接文件所指向的文件的信息。用fopen打开一个符号连接文件进行操作时,操作实际上是施加于符号连接文件所指向的文件的。

创建一个指向testfile文件的硬连接文件,意思就是创建一个文件名,这个文件名指向testfile所指向的那个inode。用link命令来创建一个硬连接文件:
[whb@jcwkyl test]$ link testfile hardlink
[whb@jcwkyl test]$ stat hardlink 
  File: `hardlink'
  Size: 25              Blocks: 8          IO Block: 4096   regular file
Device: 802h/2050d      Inode: 9306116     Links: 2
Access: (0664/-rw-rw-r--)  Uid: (  500/     whb)   Gid: (  500/     whb)
Access: 2010-01-06 16:16:27.000000000 +0800
Modify: 2010-01-06 16:16:27.000000000 +0800
Change: 2010-01-06 16:23:20.000000000 +0800
可以看到,hardlink文件的类型是regular file,它的inode号和testfile的inode号完全一样,它的Links是2,这是一个inode的引用计数。当删除hardlink或者删除testfile时,它的Links会减小为1,如果把剩下的那个文件再删掉,它的Links就成了0,此时操作系统就会把文件从磁盘上删除。
文件名相当于是一个指针,它指向一个inode,目录相当于是一个二级指针,它指向一个文件名列表。不能创建一个指向目录的硬连接。

创建一个硬连接也不等于复制文件。复制文件会在磁盘上做内容拷贝,创建硬连接只不过是创建一个指针。“复制文件”和“创建文件的硬连接”的共同点是都要求源文件必须存在。因此,不能跨文件系统或者跨分区创建硬连接。例如:
[whb@jcwkyl test]$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              49G  9.2G   37G  20% /
/dev/sda2              49G   11G   36G  24% /home
/dev/sda1              99M   19M   75M  21% /boot
tmpfs                1013M     0 1013M   0% /dev/shm
/dev/sda6             191G   36G  146G  20% /vm
看到我的/home是/dev/sda2,/boot在/dev/sda1上,创建一个/boot下某文件的硬连接:
[whb@jcwkyl test]$ link /boot/System.map-2.6.18-92.el5 map
link: cannot create link `map' to `/boot/System.map-2.6.18-92.el5': Invalid cross-device link
出错了,因为/dev/sda2上没有 System.map-2.6.18-92.el5 map文件。

同样,因为创建硬连接只是创建一个指针,所以硬连接不占磁盘空间。上面用stat命令查看testfile和hardlink两个文件,读取的是同一个inode的信息,所以大小自然一样,但是用du命令来查看,它会把指向同一个inode的多个硬连接文件自动只算一份:
[whb@jcwkyl test]$ du -hs *
4.0K    hardlink
[whb@jcwkyl test]$ ls
hardlink  testfile
再用一个例子来验证。在上面df -h的输出中能看到,/dev/sda6分区剩余146G空间,进入这个分区做个实验:
[whb@jcwkyl test]$ cd /vm
[whb@jcwkyl vm]$ du -hs *
5.1G    centos.vdi
du: cannot read directory `lost+found': Permission denied
1.5G    rh9img.vdi
54M     share
8.1G    vm1_clone.img
8.1G    vm1_convert.img
987M    vm1.vdi
936M    vm2.vdi
937M    vm3.vdi
1.6G    winxp_slave.vdi
7.4G    winxp.vdi
1.6G    xen-images
看到winxp.vdi文件有7.4G,我们为这个文件创建100个硬连接:
[whb@jcwkyl vm]$ for ((i=1; i <= 100; i++)) ; do link winxp.vdi winxp.vdi_$i ; done

[whb@jcwkyl vm]$ ls
centos.vdi       winxp.vdi_13  winxp.vdi_28  winxp.vdi_42  winxp.vdi_57  winxp.vdi_71  winxp.vdi_86
lost+found       winxp.vdi_14  winxp.vdi_29  winxp.vdi_43  winxp.vdi_58  winxp.vdi_72  winxp.vdi_87
rh9img.vdi       winxp.vdi_15  winxp.vdi_3   winxp.vdi_44  winxp.vdi_59  winxp.vdi_73  winxp.vdi_88
share            winxp.vdi_16  winxp.vdi_30  winxp.vdi_45  winxp.vdi_6   winxp.vdi_74  winxp.vdi_89
vm1_clone.img    winxp.vdi_17  winxp.vdi_31  winxp.vdi_46  winxp.vdi_60  winxp.vdi_75  winxp.vdi_9
vm1_convert.img  winxp.vdi_18  winxp.vdi_32  winxp.vdi_47  winxp.vdi_61  winxp.vdi_76  winxp.vdi_90
vm1.vdi          winxp.vdi_19  winxp.vdi_33  winxp.vdi_48  winxp.vdi_62  winxp.vdi_77  winxp.vdi_91
vm2.vdi          winxp.vdi_2   winxp.vdi_34  winxp.vdi_49  winxp.vdi_63  winxp.vdi_78  winxp.vdi_92
vm3.vdi          winxp.vdi_20  winxp.vdi_35  winxp.vdi_5   winxp.vdi_64  winxp.vdi_79  winxp.vdi_93
winxp_slave.vdi  winxp.vdi_21  winxp.vdi_36  winxp.vdi_50  winxp.vdi_65  winxp.vdi_8   winxp.vdi_94
winxp.vdi        winxp.vdi_22  winxp.vdi_37  winxp.vdi_51  winxp.vdi_66  winxp.vdi_80  winxp.vdi_95
winxp.vdi_1      winxp.vdi_23  winxp.vdi_38  winxp.vdi_52  winxp.vdi_67  winxp.vdi_81  winxp.vdi_96
winxp.vdi_10     winxp.vdi_24  winxp.vdi_39  winxp.vdi_53  winxp.vdi_68  winxp.vdi_82  winxp.vdi_97
winxp.vdi_100    winxp.vdi_25  winxp.vdi_4   winxp.vdi_54  winxp.vdi_69  winxp.vdi_83  winxp.vdi_98
winxp.vdi_11     winxp.vdi_26  winxp.vdi_40  winxp.vdi_55  winxp.vdi_7   winxp.vdi_84  winxp.vdi_99
winxp.vdi_12     winxp.vdi_27  winxp.vdi_41  winxp.vdi_56  winxp.vdi_70  winxp.vdi_85  xen-images

100个硬连接创建成功,用df命令查看分区空间使用情况,和刚才无异。如果是复制文件,不说速度,也早就报磁盘空间不足的异常了。

上面是硬连接。软连接也叫符号连接(symbolic link),它本身是一个独立的文件,指向一个新的inode,只不过在操作它时会识别出它是一个符号连接,从而所有操作都施加于它所指向的文件指向的inode上。例如:
[whb@jcwkyl test]$ ln -s testfile symboliclink
[whb@jcwkyl test]$ stat symboliclink 
  File: `symboliclink' -> `testfile'
  Size: 8               Blocks: 0          IO Block: 4096   symbolic link
Device: 802h/2050d      Inode: 9306117     Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (  500/     whb)   Gid: (  500/     whb)
Access: 2010-01-06 16:45:14.000000000 +0800
Modify: 2010-01-06 16:45:09.000000000 +0800
Change: 2010-01-06 16:45:09.000000000 +0800
可以看到,它的文件类型是symbolic link,它的inode号是9306117(testfile和hardlink的inode号是9306116),它的Links是1。软连接不影响一个inode的引用计数。

总结如下:
软连接相当于一个快捷方式。
不能为目录创建硬连接,但可以为目录创建软连接。
不能跨文件系统或者跨分区创建硬连接,但可以创建软连接。