【Linux】软硬链接和动静态库

一、如何理解目录
所以我们说Linux下一切皆文件,那么目录是文件吗?是的,因为它也有自己的inode,我们可以通过ls -i的命令来查看我们目录对应的inode

目录的内容就是该目录下文件的文件名和对应文件的inode映射关系,这样我们就可以在目录中打开文件

每个目录创建出来都会有两个隐藏文件一个是.一个是..,它们的本质是什么,它们作为一个文件的属性和内容是什么,通过下面的学习我们会知道

二、软链接
我们先来通过ln -s给我们的test目录上个软链接

我们发现这个软链接是有自己的inode的,我们前面说过,操作系统只认inode而不是文件名,所以它也是一个独立的文件,其实它的数据块里保存的是指向的文件的路径,软链接就相当于我们电脑上的快捷方式,我们对软链接进行操作,发现原文件会发生变化
当我们的原来的文件删除后,如下图

我们发现变红了,失效了,说明软链接对原文件是有依赖性的,源文件被删除软链接就会失效

三、硬链接
通过命令ln建立硬链接

我们可以看到,硬连接的inode与原文件的inode是相同的,我们在前面提到过,这里第三列的2是硬链接数,现在我们可以很清楚地解释了,硬链接数就是多个文件同时使用一个inode的数字,有多少文件硬链接数就是多少

我们修改file文件,对应的硬连接也会发生修改,因为它们就是一个文件

当我们将file文件删除,我们会发现,硬链接数变成了1,并且我们就算打开硬链接其中的数据也不会消失,这更加证明了操作系统只认inode不认文件名,因为inode结构体中,有一个引用计数的计数器,它就是硬链接数,同一inode下,只要引用计数数大于0,那么这个文件的所有硬链接以及这个文件都共用这个inode,共用一块空间

 

但是我们的操作系统是不允许我们自己对目录建立硬链接,原因有四:

1.避免文件系统循环引用:如果允许对目录创建硬链接,可能会形成目录的循环引用,例如,目录 A 通过硬链接指向目录 B,而目录 B 又通过硬链接指向目录 A,这样就会形成一个无限循环,当文件系统进行某些操作,如递归遍历目录树时,就会陷入死循环,导致系统资源被无限消耗,最终可能使系统崩溃

2.保证文件系统的一致性:目录在文件系统中起着组织和管理文件的重要作用,其结构的稳定性对于文件系统的正常运行至关重要,硬链接的特性使得多个文件名可以指向同一个 inode,如果对目录创建硬链接,可能会破坏目录结构的清晰性和一致性,例如,一个文件可能会出现在多个不同的目录层次中,这会让用户和系统难以确定文件的真实位置和归属,增加文件管理的复杂性

3.简化文件系统的实现和管理:文件系统通过 inode 和链接计数来管理文件和目录,对于文件的硬链接,链接计数可以准确地反映有多少个文件名指向同一个 inode,但对于目录来说,如果允许创建硬链接,链接计数的管理会变得非常复杂。因为目录的结构和内容不仅与自身的 inode 相关,还与父目录和子目录的关系有关,增加目录的硬链接会破坏这种简单的管理机制,使得文件系统的实现和维护变得更加困难

4.安全性:目录的权限和访问控制是基于其层次结构进行管理的,如果允许对目录创建硬链接,会使权限和访问控制的管理变得复杂,例如,一个用户可能通过硬链接绕过原本的权限设置访问到其他目录下的文件,从而破坏了文件系统的安全性

四、目录中的.和. .
1、.

还记得我们的.的作用是什么吗,就是定位当前目录,有了它我们才可以进行./相对路径的定位,通过图片我们可以发现,test的inode和test中.的inode是一样的,这是一个硬链接,一个当前目录的硬链接,操作系统虽然不让用户创建硬链接,但是为了方便我们使用相对路径进行定位,它给我们默认创建这个硬链接,并且,这是一个隐藏文件,在搜索的时候默认是不会理会的

2、. .

我们来看一下…的inode,与2_9的.的inode相同,所以…这个就是上级文件2_9的硬链接,所以这样的一切就解释通了,当我们在test目录下执行cd ..指令的时候,其实就是执行了cd 2_9

五、静态库
1、生成静态库
由两个.o文件打包生成一个静态库,其中一个是打印功能,一个是加减乘除法的功能

 

 

首先定义一个lib变量mylib.a,表示要生成的静态库文件名lib=mylib.a,然后写出生成静态库生成所需要依赖的目标文件$(lib):cal.o print.o写出它们的依赖方法ar -rc $@ $^,这个命令用于将所有的依赖文件$^打包成静态库$@,然后通过c文件生成目标文件对应的依赖文件,最后的output是一个发布规则, 目标的作用是把编译好的静态库文件和对应的头文件整理到特定的目录结构中,这在库的发布、分发以及管理方面有着重要意义

这里的静态库.a文件实际上就是多个.o文件打包而已

然后make一下生成静态库,make output将库发布,然后我们把生成的静态库lib复制到test文件夹中,进行测试,写一个测试文件

2、静态库的使用

 

我们发现它报错了,没有找到cal.h头文件,我们以前就知道,C语言包含头文件有两种形式,一种是<>,另一种就是" “,<>表示到系统指定的目录下寻找头文件,” "指的是在同级目录下寻找头文件,但是我们的头文件不在我们的同级目录下,而是在我们的同级目录lib的下级目录下,就需要以其他方式来寻找头文件,一种方法是,把代码中的路径补全,另一种方法是,将头文件拷贝到系统指定目录中,一般为/usr/local/include/或/usr/local/lib,还有一种方法是,gcc编译的时候加上-I选项,指定编译器搜索头文件的路径

 

这样我们就把头文件问题解决了,但是我们还是没办法进行编译,因为它们无法进行链接,这是由于gcc的默认搜索路径为动态库lib64/libc.so和静态库lib64/libc.a,所以我们要进行指定搜索路径

 

这里的gcc main.c -I ./lib/include -L ./lib/mylib/ -lmylib生成可执行程序有三个选项

-I是指定头文件搜索路径
-L是指定库文件搜索路径路径,如果
-l是指定库路径下要链接的库名

另一种方式就是安装库,把头文件.h复制到指定目录usr/include和库文件.a复制到指定目录lib64中,还有一种方式就是建立软链接,不过软链接类似于上面路径补全的方式#include <mysoftlink/cal.h>大概这个样子,因为我们软链接的内容就是指向位置的路径

我们把静态库删掉看看,程序是不是还能跑

六、动态库
1、动态库生成
我们拿同样的程序进行动态库的生成

这里在生成.o文件是要使用gcc的-fPIC选项,这个选项的作用是产生与位置无关码,主要是为了让生成的代码不依赖于特定的内存地址,从而使动态库可以被加载到任意的内存地址并正确运行

生成.so文件时的-shared选项就是要生成动态库文件,因为动态库也叫共享库

2、动态库使用
我们把动态库放到test文件夹中,创建一个main.c测试文件,在make的时候又遇到了找不到头文件的错误

我们按照使用静态库的方法使用动态库,发现虽然生成了可执行文件,但是连接不到动态库

我们使用ldd a.out指令查看可执行文件a.out连接的库,发现动态库这里是not found的

使用file a.out可以看到dynamically linked(uses shared libs)a.out连接的就是动态库

所以我们也有方法去解决这些问题
1、拷贝到系统默认的库路径usr/lib64 或lib64(最常用,因为我们使用的库多数都是成熟库)
2、在系统默认的库路径usr/lib64或lib64下建立软链接
3、将自己的库所在的路径,添加到系统的环境变量LD_LIBRARY_PATH中
4、在etc/ld.so.conf.d 建立自己的动态库路径的配置文件,然后使用命令ldconfig更新一下配置即可

————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/s_little_monster/article/details/145536405

阅读剩余
THE END