对于硬连结和符号连结的个人理解

sh/bash/dash/ksh/zsh等Shell脚本
回复
头像
老太
帖子: 7
注册时间: 2007-07-15 9:45
联系:

对于硬连结和符号连结的个人理解

#1

帖子 老太 » 2008-12-10 12:04

在Linux中创建文档或者目录的快捷方式有两种(类似Windows中的快捷方式),硬连结和符号连结。两者的区别如下:
1、硬连结,用来创建文档的快捷方式。实际上是在文档所在目录的block区域添加了文档的关联数据inode。因此当创建一个硬连结指向一个文档时,这个硬连结实际上表示指向了一个文档的inode。因此对该连结进行访问,实际上是通过存储的inode信息来找到文档的数据域。所以如果删除该链接,删除的只是对应的 inode信息,并不会影响原文档在原目录下的关系。如果删除原档案,实际上删除的是该文档的关联数据inode,而数据域仍然可以通过其他关联的 inode读取出来(即通过硬连结读取)。该方式不能跨分区创建连结。
2、符号连结,可以用来创建文档和目录的快捷方式。它与硬连结的不同在于,它实际存储的不是文档的关联数据inode,而是实际的数据域(block),因此给一个文档做多少个符号链接,如果删除其中一个或者删除原文档,那么该文档的数据域就会被删除 ,因此其它的符号链接是无法再次读取数据的。该方式可以跨分区创建连结。

以上是硬连结和符号连结的一般概念。对于很多像我一样的新人来说硬连结和符号链接都搞的不太清楚,主要是Linux的一些基本概念没有清楚的原因。所以如果要理解这上面的概念,首先必须理解Linux系统中的 inode和block的概念。其次如果有一定的开发经验或者C方面的概念,那么理解起来更方便。
我个人理解:实际上硬连结就像给一个数据起了一个别名,符号链接就像一个指向了该数据的指针。因此如果数据有多个别名,那么删除任意一个都不会影响原数据,其它的别名照样可以访问。如果是符号链接,访问数据的时候就像通过C语言的*来访问指针指向的数据,如果删除了该指针指向的内容,那么原数据肯定会被删除。其它指向该数据的指针也无法访问该数据。

我觉得这样理解可能更直观一些。
poet
帖子: 2841
注册时间: 2006-09-11 22:47

Re: 对于硬连结和符号连结的个人理解

#2

帖子 poet » 2008-12-10 12:52

其实上面的话,简单的说就是:硬连接指向inode,符号链指向硬连接。

1。 inode 存储实际的数据,它本身没有名字。
2。所有的文件项(direntry)都是指针,都对应一个硬连接。所有普通的硬连接都指向inode。硬连接并不是快捷方式!硬连接就是文件项本身。你创建的每个普通文件都是硬连接。
3。所有的符号链都是指向某个硬连接的指针,你可以认为它是指针的指针。——一个特别指出是,符号链仅仅描述文件路径,因此它可能指向一个完全不存在的文件名,而这个文件名并不对应一个硬连接。

4。删除任何符号链对原数据没有任何影响,因为符号链只是指针的指针,并不影响原来的数据。(这一点,楼主主贴的最初描述似乎是错误的)
5。删除任何硬连接对原数据也没有任何影响,但是有一种特例就是当某个inode连接数为零时会被系统删除。因此如果一个文件的所有硬连接都被删除,那么inode就被删除。
6。文件被打开时也会在内存中创建一个硬连接,关闭时释放。因此即使所有磁盘上的硬连接都被删除,但内存中还存在一个硬连接,这个inode也不会被删除。
头像
老太
帖子: 7
注册时间: 2007-07-15 9:45
联系:

Re: 对于硬连结和符号连结的个人理解

#3

帖子 老太 » 2008-12-10 13:15

ls说的有道理。实际上两种连结方式只能类似于windows的快捷方式,而跟快捷方式还是有一定区别。这点我没有注意。
刚才又仔细学习了下连结方式。发现自己的理解有问题。
硬连结的连结档案和原档案实际上是同一个档案,只不过分别由两个目录记录了该档案的关联数据。所以删除时,删除的只是它的上层目录中记录的该档案的关联数据,档案本身的inode和block并没有删除。所以数据仍然可以访问。
对于符号连结,应该和windows快捷方式一样。刚才我说删除掉任意一个指向文档,则导致别的指向无法访问,这一点是有问题的。应该是如果删除掉原文档,那么符号连结所指向的内容已经被删除,所以再也打不开了。
至于ls说的指针的指针这一点还是没有太理解。个人还是觉得以一层指针去理解比较贴切。


谢谢ls
头像
ptptptptptpt
帖子: 3711
注册时间: 2006-09-19 18:16

Re: 对于硬连结和符号连结的个人理解

#4

帖子 ptptptptptpt » 2008-12-10 13:29

poet 写了: 6。文件被打开时也会在内存中创建一个硬连接,关闭时释放。因此即使所有磁盘上的硬连接都被删除,但内存中还存在一个硬连接,这个inode也不会被删除。
假如此时关闭文件,内存被释放,inode 是不是也会被删除??

另外,什么情况下, 一个 inode 会有多个硬链接呢??
头像
xhy
帖子: 3916
注册时间: 2005-12-28 1:16
系统: Ubuntu 12.10 X64
来自: 火星

Re: 对于硬连结和符号连结的个人理解

#5

帖子 xhy » 2008-12-10 15:13

仅针对普通文件 不针对目录

以ext3文件系统为例
inode指向若干个data block,对于小文件data block中存储的就是文件内容
对于大文件,inode指向的data block指向其它data block(第二层data block),第二层的data block中存储文件内容
如果文件大到两层存不下,那么会分成3层或者更多层来存储

从跟具体文件系统无关的层次看
ln创建符号连接时调用了symlink,创建连接时调用了link,本质上,分别是sys_link和sys_symlink这两个系统调用
这两个系统调用的核心由vfs_link和vfs_symlink实现,实际上是交给了文件系统来实现,文件系统注册时提供了相应的接口而已

各个文件系统对vfs_link和vfs_symlink的理解可能不完全一样,大体上是差不多的
inode上存储了引用计数,一个文件被创建时,就会在它的inode上设置引用计数,
当创建一个连接指向它时,引用计数+1,而创建一个符号连接指向它时,引用计数不会+1
删除连接时,引用计数-1,删除符号连接时,引用计数不会-1
一个inode的引用计数为0时,它将被删除掉(若i_count也为0)
这就造成了删除连接和符号连接的区别(假设这个删除不跟随符号连接)

连接之所以不能跨越文件系统,是因为inode体系只属于一个文件系统,两个文件系统可能有相同的inode
(某些实现允许这么做,特殊方法实现)

符号连接存储在一个block中,因此指向的路径名不能太长,否则存储不下,具体数值是inode->i_sb->s_blocksize

源码是最好的参考
目前负债150多万
头像
xhy
帖子: 3916
注册时间: 2005-12-28 1:16
系统: Ubuntu 12.10 X64
来自: 火星

Re: 对于硬连结和符号连结的个人理解

#6

帖子 xhy » 2008-12-10 15:52

打开文件不会创建硬链接,只是把inode->i_count加一
目前负债150多万
头像
Jarson
帖子: 2371
注册时间: 2008-07-21 9:44
来自: 深圳
联系:

Re: 对于硬连结和符号连结的个人理解

#7

帖子 Jarson » 2009-03-21 20:39

LS各位分析的十分清晰透彻
学习了~~
bluestar0817
帖子: 16
注册时间: 2009-03-13 9:21

Re: 对于硬连结和符号连结的个人理解

#8

帖子 bluestar0817 » 2009-03-24 10:13

xhy 写了:仅针对普通文件 不针对目录

以ext3文件系统为例
inode指向若干个data block,对于小文件data block中存储的就是文件内容
对于大文件,inode指向的data block指向其它data block(第二层data block),第二层的data block中存储文件内容
如果文件大到两层存不下,那么会分成3层或者更多层来存储

从跟具体文件系统无关的层次看
ln创建符号连接时调用了symlink,创建连接时调用了link,本质上,分别是sys_link和sys_symlink这两个系统调用
这两个系统调用的核心由vfs_link和vfs_symlink实现,实际上是交给了文件系统来实现,文件系统注册时提供了相应的接口而已

各个文件系统对vfs_link和vfs_symlink的理解可能不完全一样,大体上是差不多的
inode上存储了引用计数,一个文件被创建时,就会在它的inode上设置引用计数,
当创建一个连接指向它时,引用计数+1,而创建一个符号连接指向它时,引用计数不会+1
删除连接时,引用计数-1,删除符号连接时,引用计数不会-1
一个inode的引用计数为0时,它将被删除掉(若i_count也为0)
这就造成了删除连接和符号连接的区别(假设这个删除不跟随符号连接)

连接之所以不能跨越文件系统,是因为inode体系只属于一个文件系统,两个文件系统可能有相同的inode
(某些实现允许这么做,特殊方法实现)

符号连接存储在一个block中,因此指向的路径名不能太长,否则存储不下,具体数值是inode->i_sb->s_blocksize

源码是最好的参考
豁然开朗!!!! :em01
回复