Linux基础IO【软硬链接和动静态库】
平时我们在运行软件时并不会到软件目录中去找到.exe
文件来打开,而是直接从桌面双击快捷方式运行,这个快捷方式就是其对应的软链接
文件,下面就来一起看看软硬链接和动静态库的相关知识吧
1. 软硬链接
1.1 现象理解
通过指令ln -s
,就可以对文件进行软链接
ln -s 文件名 软链接文件名 //生成软链接文件
通过指令ln
,即可对文件进行硬链接
ln 文件名 硬链接文件名 //生成硬链接文件
软硬链接的文件可以和源文件一样使用
软硬连接的区别
软链接是一个独立的连接文件,有自己独立的
inode
号,就有自己的属性,同时软链接文件指向源文件(依赖于),大小比源文件小得多硬链接和目标文件共用同一个
inode
,大小与源文件一样大,硬链接的本质就是建立了新的文件和inode
的映射关系,相当于给文件起别名
如果我们删除源文件,软链接将会失效,而硬链接依然有效
1.2 链接原理
软链接原理
- 软链接文件是一个单独存在的文件,有自己的
inode
属性及相应的文件内容,在软连接的Data block
中存放的是源文件的地址,因此软连接很小,并且依赖于源文件 - 源文件被删除,软链接文件就会失效,因为此时里面存放的已经是一个无效的地址,相反如果删除软链接文件,对源文件的内容没有影响,就比如在
Windows
下删除桌面的快捷方式一样
硬链接原理
- 硬链接实质上就是一个指针,指向文件索引节点,硬链接的本质就是把源文件的属性拷贝一份,然后把文件名改一下即起别名,该文件名对目标文件
inode
做映射,直接指向目标文件inode
- 源文件有对应的
inode
结构体,其中有用来记录硬链接数量的变量,硬链接后,硬链接文件和源文件inode
一样,并且此inode
中的硬链接数变量进行+1
操作,表示当前已成功硬链接上了一个文件 - 当删除当前
inode
对应文件时,会先判断硬链接数变量是否为1
,如果是,才会将文件内容及其属性真正删除,否则删除的只是文件名与inode
编号的映射关系。所以删除源文件后,硬链接文件不受影响,只是硬链接数-1
,同样的,删除硬链接文件,也不会影响源文件
新建目录的硬链接数默认为2
,这是为什么呢?
- 因为目录中默认存在两个隐藏文件,
.
表示当前目录,..
表示上级目录 - 将目录的硬链接数
-2
,就可以得到当前目录下的目录数量了
不能手动给目录建立硬链接
Linux
下的目录结构为多叉树结构,当目录需要与上级目录和下级目录建立链接关系,为了避免用户的链接操作导致目录成环问题,规定只能由OS
自动给目录建立硬链接
1.3 应用场景
当一个文件层次太深时,可以直接软链接在当前目录对其进行相关操作
硬链接一般用来当目录移动个工具,再就是给文件起别名来使用,确保源文件不被破坏
1.4 取消链接
通过指令unlink
,可以取消链接关系
当然也可以暴力点,直接删除链接文件来取消链接
2. 动静态库
2.1 初识库
Linux下库分为静态库和动态库
- 静态库:后缀为.a,程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
- 动态库:后缀为.so,程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码
Windows
下, 静态库后缀为.lib
,动态库后缀为.dll
库的命名规则
- 库命名:开头(lib) + 命名 + 后缀(.a / .so)
- 例如,
libstdc++.so.6
,去掉前缀和后缀就得到了stdc++
,也就是库名
Linux的库在/usr/lib64
目录下
find /usr/lib64/libc*
头文件在/usr/include
目录下
2.2 库的意义
这里的库到底是什么呢?头文件又是什么呢?
- 打开一个库文件,我们发现它是个二进制文件,头文件我们打开发现都是函数的声明,而库中对应的就是对应函数功能实现,头文件在预处理阶段就已经引入了,链接的本质就是在链接库
- 我们在安装编译器软件的时候,其实就是安装头文件和库文件。另外还有使用编译器的时候,编译器会有自动提醒头文件或者函数等功能,这些都是通过遍历头文件和库文件来匹配完成检索的,还有语法报错功能,这也是编译器来进行检索功能
所以库的作用到底是什么呢?
- 头文件和对应的库文件一安装环境就有了,其中的功能接口可以直接拿来用,不用自己造轮子,这样就提高了开发效率
3. 静态库制作
先提供一个加减方法
我们可以将其打包成静态库
3.1 静态库打包
静态库的打包步骤:
第一步:将源文件进行预处理->编译->汇编,生成可链接的二进制.o
文件
gcc -c 源文件
第二步:使用ar
指令将.o
文件打包成静态库
ar -rc lib库名.a *.o //生成静态库
这样静态库就打包好了
通过指令ar -tv
可以查看静态库中的具体文件
3.2 静态库使用
第一种方法:通过指定路径使用静态库
自己写的第三库,需要注明三个参数才能使用:
- -I + 所需头文件的路径
- -L + 所需库文件的路径
- -l + 待链接静态库名
gcc -o 目标文件名 源文件名 -I头文件路径 -L库文件路径 -l静态库名
为什么编译 C/C++
代码时,不需要指定路径?
- 因为使用的库都是系统级的,
gcc/g++
默认就是stdc/stdc++
系统库里面找
第二种方法:将头文件和静态库文件安装至系统目录中,这里需要指定静态库名
sudo cp ./头文件名/*.h /usr/include/
sudo cp ./静态库文件名/*.a /lib64/
注意:将自己写的文件安装到系统目录下,使用完后记得手动删除,避免造成系统环境污染
4. 动态库制作
4.1 动态库打包
动态库是通过与位置无关码,来达到对指定的函数进行链接使用
动态库的打包步骤:
第一步:还是编译源文件来生成二进制可链接文件,需要加上与位置无关码-fPIC
gcc -c -fPIC *.c
这时候生成的.o
文件中就有了与位置无关码
第二步:使用gcc/g++
直接将所有的.o
文件打包成动态库,需要加上-shared
选项
gcc/g++ -o lib动态库名.so *.o -shared //打包动态库
这样动态库就打包好了
4.2 动态库使用
像使用静态库一样,通过指定路径和动态库库名来使用动态库
这里我们发现编译成功了但是运行程序却失败了,这是为什么呢?
- 这是因为当前只告诉了
gcc
编译器动态库的位置,并没有告诉OS
我们通过指令ldd
来查看一下程序的链接情况
可以发现当前的状态是未链接
这里有三个方法可以让OS链接动态库
方法一:环境变量法(临时方案)
将动态库路径添加到 LD_LIBRARY_PATH
环境变量中,环境变量,LD_LIBRARY_PATH
是程序在进行动态库查找时的默认搜索路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库路径
环境变量重新登录后会失效,所以这是个临时方法
方法二:软链接法
在 /lib64/
目录下建立动态库的软链接,将动态库的软链接文件存入系统目录中
sudo ln -s 动态库文件绝对路径/动态库文件名 /lib64/动态库文件名
注意:创建软链接文件时,必须使用绝对路径!
方法三:配置文件法
各种动态库配置文件在/etc/ld.so.conf.d
目录中,创建.conf
文件,文件中存储第三方动态库的路径,然后将文件移动到此目录中,通过指令ldconfig
使配置文件生效(更新配置文件)
echo 动态库文件绝对路径 > .conf文件
sudo mv .conf文件 /etc/ld.so.conf.d/
sudo ldconfig
方法二和方法三都存入了系统目录中,是永久有效的
5. 动静态库加载和补充
5.1 动静态库加载
静态库加载
- 当程序形成可执行程序的时候,这个可执行程序中已经包含了静态库中被转化为二进制代码的函数功能实现,此时形成
.exe
文件后,把静态库删除了依旧可以运行正常,这相比动态库,静态库的可执行文件要大的多,因为动态库中被转化为二进制程序的函数功能实现并不是直接拷贝到.exe
文件中的。所以总结出一个结论:静态库非常占用资源(磁盘资源等)
动态库加载
- 程序在链接动态库函数时,是通过
动态库起始地址
+所链接函数偏移量
的方式进行链接访问的,而这个偏移量就是fPIC
与位置无关码
解释一下这个图
- 这里需要注意的是虚拟内存空间中有共享区这个区域,这个区域就是用来存放应的动态库文件中相关库函数名的地址,运行程序时,需要用到某个函数时就对应的把动态库文件也加载到内存中,通过函数名地址在共享区找相对应的函数地址,然后加载到物理内存中,再给CPU进行计算
- 所以,把对应的动态库文件删除,就好像找不到相对应的函数,并且它是只有一份的,这样就可以随时拿来使用,没有静态库那么占用资源
上面动态库使用中我们用到了-fPIC
这个选项,它与位置无关码是什么呢?
- 也就是这里的函数名调用和函数地址对应关系和位置并不相关,可以这样理解:每次加载到内存中虚拟内存中的共享区这个区间的起始地址是不一样的,这里是根据对应的起始位置的偏移量找到函数实现的,所以和位置(绝对位置)无关
5.2 知识补充
生成静态链接文件,只需要加上-static
选项即可
gcc -o 目标文件名 源文件名 -I头文件路径 -L库文件路径 -l静态库名 -static
链接补充
- 编译器进行链接的时候,如果同时有动态库和静态库,优先动态链接,没有动态库只有静态库时,只能静态链接;如果都没有,则程序运行不了
- 只有静态库,又不指定静态链接,会默认使用动态链接,生成的程序内含有静态库
Linux基础IO【软硬链接和动静态库】,到这里就介绍结束了,本篇文章对你由帮助的话,期待大佬们的三连,你们的支持是我最大的动力!
文章有写的不足或是错误的地方,欢迎评论或私信指出,我会在第一时间改正