最近看到很多文章介绍Linux中的文件系统,包括inode节点、软链接、硬链接等重要概念。于是有朋友私信问我:这些概念我都懂了,但是我能用它们来完成什么?或者,在什么情况下,软链接和硬链接能提供更好的解决方案?本篇文章,我们简单梳理一下软链接和硬链接的几种使用场景。什么是索引节点?什么是硬链接?什么是软链接?软链接应用:目标程序不同版本的灵活切换软链接应用:动态库版本管理分类硬链接应用:多人共享文件;文件内容:即文件中存储的数据;文件描述信息:文件类型、所有者、创建时间等,可以称为元信息;可以做一个简单的类比:文件本身的内容可以当真人看。档案的描述信息可以看作是派出所的户口卡。户籍卡记录了一个人的姓名、年龄、住址等信息。通过这张户口卡,警察叔叔知道了这个人的所有描述信息,除了你脑子里的知识。回到计算机,文件的所有信息都需要存储在硬盘上,所以需要将硬盘划分为区域:不同的区域存储不同类型的数据,这就是文件系统的重要作用。在Linux系统使用的ext2/ext3文件系统中,从硬盘上划出一块区域来存放文件本身的内容(数据)。这个区域是按照一个最小单位划分的:块。然后在硬盘上再划分一个区域,专门用来存放所有文件的描述信息。每个文件的描述信息由一个称为索引节点(inode)的数据结构来表示,所有文件的inode都统一放在这个硬盘区域。就像一个人的地址记录在户口簿上一样,文件的所有描述信息也记录在文件的索引节点(inode)中,包括:文件类型、所有者、创建时间等,当然还有filecontent硬盘中存储了哪些块。当我们调用打开文件API函数时,操作系统首先根据传入的文件路径找到文件的inode,然后进行一系列的权限检查操作,最后得到文件内容存储在哪些块(blocks)中infromtheinode),这样就可以读写文件的内容了。文件名只是我们用户使用的,操作系统只是通过inode节点来管理文件。当我们创建一个新文件的时候,同时创建了这个文件对应的inode节点。当我们删除一个文件时,同时删除了该文件对应的inode节点。此时,文件本身内容所在的块中的数据不会被擦除,所以一些数据恢复软件就是利用这个特性来找回数据。一句话概括:索引节点(inode)就像一张户口卡,操作系统通过inode管理所有的文件。刚才提到了硬链接,每个文件对应一个inode节点。比如有一个文件a.txt,文件内容的长度为1024字节,存放在硬盘的某个块中,假设是第10000块。那么在这个文件对应的inode节点中,会记录block10000。同时它还有一个links字段,意思是:当前inode对应一个文件,此时inode.links的值为1。这时候如果我们使用另外一个文件名a_hard_link.txt,它也会代表文件a.txt。也就是说:虽然我们使用了2个文件名,但它们本质上指向同一个文件,内容都指向第10000块存储的文件内容。Linux系统提供了硬链接来支持这个目的。它只是将inode节点中的links字段的值加1,即inode.links的值变为2。硬链接的操作指令为:$lna.txtb.txt基于硬链接,用户可以使用不同的文件名访问同一个文件,所有操作最终修改的是同一个文件。如果仅从用户的角度来看,似乎我们在操作不同的文件,但是这些文件具有自动同步的功能。这个行为有点类似于网盘:在云存储中有一个文件hello.txt,然后我有两台电脑A和B,这两台电脑会在本地为云中的文件hello.txt创建一个镜像文件,就好像这个文件在你自己的硬盘上。当我在A电脑上操作hello.txt时,B电脑上的同名文件会自动更新。因此,从行为上来说,硬链接相当于:文件复制+自动同步。我们来看看硬链接文件的删除操作。执行完$lna.txta_hard_link.txt命令后,文件对应的inode节点中的links值为2,如果我们删除a.txt,操作系统会把a.txt对应的inode中的links值减1文件,结果为1,操作系统发现不为0,所以不会删除inode。如果我们再次删除a_hard_link.txt,操作系统再次执行inode.links减1的动作,发现值变成了0,于是删除了inode,所以这个文件根本不存在。这相当于注销了一个人的户口本。从户籍管理来看,这个人已经不存在了。就算存在,也是黑户。硬链接有两个限制:不允许用户创建到目录的硬链接,即:用户不能,操作系统可以(在每个目录中思考.和..);只有在同一个文件系统中的文件才能创建硬链接,也就是说:不能跨文件系统;软链接的引入是为了克服硬链接的两个局限性。软链接也叫符号链接,是一个独立的文件。软链接文件的内容是一个文本字符串,存放的是目标文件(即要链接的文件)的路径名。这个路径名可以指向任何文件系统中的任何文件或目录,甚至可以指向一个不存在的文件。与创建硬链接不同的是:当我们创建软链接时,操作系统会创建一个新的inode来代表软链接文件。比如有一个文件a.txt,我们创建一个软链接a_soft_link.txt指向它:$ln-sa.txta_soft_link.txt此时a.txt和a_soft_link.txt各自有自己的inode节点。图中绿色虚线表示软链接文件中的文件路径。因为软链接文件中只存储了目标文件的路径字符串,所以它可以代表文件系统中的任何文件或目录。当我们打开文件软链接a_soft_link.txt时,操作系统从a_soft_link.txt对应的inode数据结构中发现:这是一个软链接文件。于是操作系统根据其中的路径信息找到a.txt的inode节点,从而对最终的目标文件进行操作。我们来看看软链接文件的删除操作。如果我们删除目标文件a.txt,那么inode节点就会被删除,相当于它的户口卡被注销了。此时再次打开软链接a_soft_link.txt时,虽然里面的路径信息依然存在,但是此时系统已经找不到a.txt对应的inode节点了。因此,软链接类似于Windows系统中的快捷方式。当真正的目标文件被删除时,快捷方式就没有存在的意义了。软链接应用:目标程序不同版本的灵活切换在开发过程中,对于同一个工具软件,可能会安装多个不同的版本,如:Python2和Python3,JDK8和JDK9等。此时,您可以使用软链接指定当前使用的版本。例如在我的电脑中:$ll-l/usr/bin/python*lrwxrwxrwx1rootroot9Dec3108:19/usr/bin/python->python2.7*lrwxrwxrwx1rootroot9Dec3108:19/usr/bin/python2->python2.7*-rwxr-xr-x1rootroot3492624Mar204:47/usr/bin/python2.7*lrwxrwxrwx1rootroot9Dec3108:19/usr/bin/python3->python3.5*-rwxr-xr-x2rootroot4456208Jan2702:48/usr/bin/python3.5*当在终端窗口输入:python,即启动python2.7版本。如果有一天我需要使用python3.5版本,我只需要将软链接python指向python3.5即可。软链接应用:动态库版本管理在Linux系统的动态库版本管理中,有一个SONAME的概念。我们在编译动态链接库的时候,一般会使用下面的编译命令:$gcc-fPIC-shared-olibhello.sohello.c在使用这个动态库的时候,需要链接这个库:-llibhello。一个简单的demo可以这样写,但是如果遇到一些比较大的项目,需要实施严格的版本管理,应该怎么做呢?Linux系统已经为我们想到了解决方案,使用SO-NAME。首先,在编译动态链接库文件时,指定生成SO-NAME,存储在动态链接库ELF文件中。下面直接看一个优秀的开源工具libevent的例子:$ll/usr/lib/libevent-2.1.so*lrwxrwxrwx1rootroot17Jul272020/usr/lib/libevent-2.1.so->libevent-2.1.so.7lrwxrwxrwx1rootroot21Jul272020/usr/lib/libevent-2.1.so.7->libevent-2.1.so.7.0.1-rw-r--r--1rootroot412016Jul272020/usr/lib/libevent-2.1.so.7.0.1使用readelf命令查看此时生成的动态库文件libevent-2.1.so.7.0.1:$readelf-alibevent-2.1.so.7.0.1|grepSONAME0x000000000000000e(SONAME)librarysoname:[libevent-2.1.so.7]有什么好处这样做??Linux系统查找动态链接库文件时,会在以下三个默认目录中查找(当然还有其他目录,如:当前目录,LD_LIBRARY_PATH指定的目录)/lib:存放最关键的和操作系统库文件的基础文件;/usr/lib:存放一些系统运行不需要的关键库文件;/usr/local/lib:存放用户自己安装的一些第三方库文件;系统安装的所有动态链接库,借助ldconfig这个程序会自动创建、更新或删除相应的SONAME(是软链接,链接到实际的库文件),并将这些SONAME汇总到一个文件/etc/ld.so.cache用于缓存。这样,动态库加载器在查找动态库文件时,可以直接在缓存文件中查找,加快了查找动态库的速度。软链接应用:Shortcuts软链接的快捷功能更容易理解。想一想:为什么我们要在Windows桌面上创建许多软件快捷方式?在Linux中也是如此!比如:最近工作,每次都要打开一个路径很深的文件。如果在资源管理器中鼠标逐层点击,是不是很浪费时间?此时,可以在桌面创建一个软链接,每次双击都会打开链接的目标文件。硬链接的应用:从不同角度对文件进行分类比如我有一个文件夹,里面存放了10G的照片。这些照片中的人物,拍摄的地点,拍摄的时间都不一样。现在,我不仅要对照片中的人进行分类,还要对照片的拍摄地点、照片的拍摄时间进行分类。我应该怎么办?因为一张照片可能同时属于多个不同的类别,是否真的要在每个类别中复制一张照片呢?这太浪费硬盘空间了!解决办法是:所有的照片还是放在一个通用的文件夹里,然后建立不同的分类文件夹。在每个类别文件夹中,创建指向目标照片文件的硬链接。这样一来,不仅照片归类了,而且硬盘空间也完全不被占用。硬链接应用:多人文件共享当很多人同时维护同一个文件时,如果每个人都直接操作文件,如果不小心删除了文件,大家就完蛋了!这时候,你可以在每个人自己的私有目录下,建立一个硬链接。每次只需要对这个硬链接文件进行操作,所有的改动都会自动同步到目标文件中。由于大家都在操作硬链接文件,即使不小心删除了,文件也不会丢失。因为删除硬链接文件只是将文件的inode节点中的links值减1,只要不为0,就不会真正删除文件。硬链接的应用:文件备份有些朋友有个好习惯,就是定期备份文件并清理。备份的时候,如果是真正的拷贝,真的是浪费磁盘空间,尤其是我这块只有256G硬盘空间的笔记本。此时可以使用硬链接功能,既实现了文件备份的目的,又节省了大量的硬盘空间,一举两得!很多备份工具都使用了硬链接功能,包括git工具。克隆本地仓库时,执行克隆命令:gitclone--reference
