详解OSX(Unix)中的Hard Link与Symbolic Link((硬连接与软连接)

前几天公司公司的一个项目中需要递归检索文件,因为我的一时疏忽,没有考虑到存在连接文件的这种情况,导致发布后的程序有可能陷入死循环的重大BUG,没少挨老大的白眼,正所谓在哪儿跌倒就在哪儿爬起,所以今天详细的解释一下”连接文件”的来世今生并分享一下我实验的结果。

熟悉Unix的朋友们,肯定对Hard link 和 soft link并不陌生的,OSX出自出Unix的血统,自然也完美的继承了这样的特性,在OSX之中的官方文档中一般称之为Hard Link和Symbolic Link。

文件系统的管理与内存管理在某些文件其实还是有很大的相似性的,比如我们要操作内存中的数据,都是通过指针去执行相应的操作的,在文件系统中也不例外。我们创建一个文件,首先会在硬盘中配一定的硬盘扇区和该文件的相关属性(如权限等),这些信息最终都存储在一个节点(inode)之中,以后我们就可以通过这个节点的地址去访问、修改、追加信息了。

硬连接

硬连接其实就是一个指向inode的地址,严格的讲,我们在文件管理中看到的每一个文件,都是一个硬连接的表现。而我们常说的创建了一个文件的一个硬连接,就是对这个地址的一个拷贝。一个inode有一个或多个这样的连接指向它,正如我们程序中使用的指针一些,使用用指针对文件的修改都会让所有指向于该节点的连接产生同样的影响。不仅如此,硬连接还拥有类似于”自动内存管理”的机制,当你删除任意的一个硬连接,只要仍然还有其它的连接指向inode节点,那么该块文件的信息都不会被释放,只有当所有指向它的连接都已经删除,它才会被置为空闲状态。

软连接

如果你深刻的理解了内存管理的原理,当然对理解上述的硬连接就不会有任何的困难了,并且对软连接的理解也不费吹灰之力,因为软连接就正好就如同内存管理中的“指向指针的指针”,软连接本质就是指向硬连接的一个地址,自然它也只会对这一个硬连接有效,一旦软连接所指向的硬连接被删除,软连接也就失效了。当然这与”指针的指针”也有一个很微妙的差别,那就是你对软链接的操作都是通过跳转到硬连接再映射到了对节点的操作,你看出来了这个微妙的差别吗?

在OSX中创建硬链接有如下两个方法:

1
2
- ( BOOL )linkItemAtPath:( NSString *)srcPath toPath:( NSString *)dstPath error:( NSError **)error;
- ( BOOL )linkItemAtURL:( NSURL *)srcURL toURL:( NSURL *)dstURL error:( NSError **)error;

创建软链接有如下两个方法:

1
2
- ( BOOL )createSymbolicLinkAtPath:( NSString *)path withDestinationPath:( NSString *)destPath error:( NSError **)error ;
- ( BOOL )createSymbolicLinkAtURL:( NSURL *)url withDestinationURL:( NSURL *)destURL error:( NSError **)error;

下面就介绍一下我对验证这些理论的实验过程吧!

实验一:软链接的实现非常简单,我直接对一个文件(你所看到的这个文件其实已经就是一个硬连接了)创建了一个SymbolicLink,然后我修改文件的名字,SymbolicLink仍然是可以正确的找到文件的,但当我删除了文件,那么SymbolicLink就永远失效了。

实验二:我先创建了一个文本文件,命名为test1.txt,并对它创建了test2.txt硬连接,然后我使用文件编辑器打开并编辑了test1.txt,然后再打开test2.txt查看内容变化,结果让我吃惊了,尼玛,test2.txt竟然没有变化,难道我理解错了?

实验三:实验二的结果让我不甘心,并猜测利用文件编辑器打开修改再次保存时并不是对原数据的修改,而是删除了原文件,并重新创建的一个文件(真正意义上的创建,分配扇区,节点……)。为证实我的猜测成立,我继续实验,仍然是创建test1.txt,并创建硬连接test2.txt,但这次修改,我不再使用文件编辑器,而是通过命令行:printf “hello” >> test1.txt,然后再打开test2.txt,哈哈,结果正如我预料中的一样,test2.txt中已经看到了我所追加的hello文字,成功!

补充:在OSX中,我们的程序对硬连接和软连接的差别:硬连接跟原来我操作的文件方式一模一样(正如我上面所讲到的,我们以往所操作的文件本身也就一个硬连接),并会被文件系统计算同样的空间,而软连接的文件size则会是一个非常小的值,通常只有几byte,另外对软连接的操作最终都会被映射成所对应文件的操作,当然我们也可以NSFileManager的destinationOfSymbolicLinkAtPath:error:方法和NSString的stringByResolvingSymlinksInPath方法来转换成原始的文件路径。

以上便是我对Hard Link与Symbolic Link的阐述,如有大神路过,请忽视!

未完待续,虽然以上实验已经让我理解并证实了Hard Link与Symbolic Link的差别,但我仍然还有一事不明白,在OSX中通过鼠标右键创建替身的这种方式所创建的连接类型是神马连接??通过实验1就排除了它是硬连接的可能,但通过NSFileManager取到的替身的NSFileType却是NSFileTypeRegular(普通文件类型),并不是软连接的NSFileTypeSymbolicLink类型,并且如果是一个文件夹的替身,在代码中使用NSFileManager的文法contentsOfDirectoryAtPath:error:并不能得到结果,这也与软连接类型的表现相矛盾,于是再猜测这完全就是OSX自创的一种连接文件类型,暂无实验!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值