【Linux】软硬链接,动静态库
目录
一、认识一下常用指令
1、建立一个软链接
2、建立一个硬链接
3、删除文件的第二种方式:删除链接unlink指令
二、什么是硬链接?
三、软硬链接的原理:
四、应用场景
1、建立一个软链接可以快速在一个比较深的路径中找到目标文件进行执行:
2、观察现象:
3、硬链接使用场景之一:
五、动态库和静态库
1、ldd:查看动态库链接
2、动静态库使用过程
静态库(.a文件)
动态库(.so文件)
3、动静态库注意事项
4、动静态库的制作和使用
(1) $^:所有依赖项列表
(2)$<:第一个依赖项
5、将.c文件链接上动静态库
I(大写i)选项
查看头文件所在路径:ls /usr/inlcude/
6、打包/安装注意事项
7、修改make文件,使动静态库都能形成
8、几个结论
六、理解动态加载
七、简单谈谈编址和可执行程序
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家
点击跳转到网站
一、认识一下常用指令
1、建立一个软链接
指令:ln -s [源文件或目录] [目标软链接]
软链接即上述的link.soft本质上也是个文件,有独立的inode。
2、建立一个硬链接
指令:
ln [源文件] [目标硬链接]
我们可以观察到两个现象:
(1)硬链接的inode和源文件相同:
所以可以知道硬链接本质不是一个独立文件,因为inode和源文件一样。
(2)我们看一个属性由数字1变成了数字2。
当我们删除硬链接或者源文件,这个数字又会由2变1:
这个属性类似于引用计数,我们称这个属性叫硬链接数
3、删除文件的第二种方式:删除链接unlink指令
该指令和rm类似:
二、什么是硬链接?
由上我们可以知道,硬链接不是一个独立文件,所以创建硬链接的过程并没有创建新文件,硬链接类似于引用计数,只是新的文件名,和源文件的inode号有映射关系。
每增加一组映射,inode结构体中存在一个引用计数就会++,也是就是硬链接数会++。
注意:
三、软硬链接的原理:
四、应用场景
1、建立一个软链接可以快速在一个比较深的路径中找到目标文件进行执行:
因为软链接保存的就是目标文件路径。
2、观察现象:
当我们创建一个文件夹时,硬链接数刚开始默认就是2,为什么呐?
因为创建一个目录的同时会默认创建两个文件
.而当前目录(.)就代表当前目录test1,所以存在两个文件名映射同一个inode,所以test1文件的硬链接数是2。
3、硬链接使用场景之一:
首先认识一个结论:计算一个目录下有多少个子目录:目录硬链接数-2
因为每个子目录都存在一个默认文件(..)代表上级目录,子目录的上级目录就是当前目录。
因为会造成环路问题,所以系统不允许我们为目录创建硬链接:
但系统可以为目录创建硬链接,比如(.)和(..);
五、动态库和静态库
1、ldd:查看动态库链接
- 左边
libc.so.6
是程序编译、运行时期望找到的动态库 “逻辑名称”(可理解为别名 )。- 右边是系统中实际存在的动态库文件路径(物理位置),系统会根据这个映射,在程序加载时找到真实的
libc.so.6
去提供功能支持。- 并且编译程序时,默认是进行动态链接,如果想要进行静态链接,需要使用选项“-static"
![]()
- 动态库后缀:.so
- 静态库后缀:.a
- 库的真实名字是去掉前面的lib,去掉后面的后缀(.so/.a)剩下的就是库真实名字,比如上述的libc.so.6真实名字就是c(c标准库)。
2、动静态库使用过程
静态库(
.a
文件)
- 编译时 “拷贝整合”:编译链接阶段,链接器会把静态库中被程序调用的代码完整复制到可执行文件里。程序运行时,无需再去外部找库,直接执行内部代码,省去了 “运行时加载库” 的开销,启动速度更快 。
- 避免运行时动态开销:没有动态加载、符号解析等运行时流程,代码执行流程更直接,对追求极致启动速度和独立运行环境(不依赖外部库)的场景友好,比如嵌入式设备里,程序可脱离外部依赖快速启动执行。
动态库(
.so
文件)
- “共享复用” 省资源:多个程序可共享同一份动态库。系统加载动态库到内存后,不同程序调用时,复用已加载的库代码,减少内存、磁盘重复存储(一个库文件给多个程序用,不用每个程序都存一份库代码),提升系统整体资源效率。
- “延迟绑定” 减启动耗时:借助 PLT(过程链接表)和 GOT(全局偏移表)实现延迟绑定 。程序启动时,不着急解析、绑定所有外部符号(函数 / 变量),第一次调用外部符号时,才去查找地址并记录到 GOT 。后续调用直接用记录的地址,避免启动时 “一次性解析所有符号” 的性能浪费,让程序启动更快,尤其适合依赖多、但实际运行不会用到全部符号的复杂程序。
3、动静态库注意事项
首先为什么要有库?
(1)为了提高效率
(2)可以隐藏源代码
库的本质就是将所有的.o文件用特定的方式进行打包整合,形成一个大文件,最后得到一堆头文件和一个库文件,但这只是简化后的概念,具体还很复杂。
注意:库里面不能含有main函数,因为main只能有一个。
4、动静态库的制作和使用
(1)gcc的-shared选项:用来打包动态库:
(2)gcc的-FPIC选项:
让动态库能被加载到任意内存地址,多个程序可共享同一份库代码(节省内存);避免因库加载地址冲突导致的链接 / 运行错误。
(3)make文件常用符号解析:
(1)
$^
:所有依赖项列表
- 含义:表示规则中所有的依赖文件,按书写顺序排列,重复的依赖项会被保留。
- 示例:若规则为
target: file1 file2 file3
,则$^
等价于file1 file2 file3
。(2)
$<
:第一个依赖项
- 含义:仅表示依赖项列表中的第一个文件。
- 示例:上述规则中,
$<
等价于file1
。
5、将.c文件链接上动静态库
# 链接动态库 gcc main.o -L./libs -lmylib -o main # 生成可执行程序 main# 若链接静态库(需确保 libs/ 目录有 libmylib.a) gcc main.o -L./libs -static -lmylib -o main # -static 强制静态链接
(1)-L后面接的是库路径,-l后面接的是指定库名
(2)gcc可以默认识别c/c++的库和系统中的路径,所以除了-L指定的路径,gcc还会去系统默认的路径中查找c/c++库。
6、发布库的过程:
I(大写i)选项
查看头文件所在路径:ls /usr/inlcude/
6、打包/安装注意事项
若直接将动态库打包过来安装后用指令编译,虽然编译可以通过,但运行时会报错:(静态库是可以的)
原因如下:
四种解决方法:
(1)
(2)认识一个环境变量:$LD_LIBRARY_PATH:
Linux里的环境变量,专门用于指定动态链接库(
.so
文件,类似 Windows 下的.dll
)的搜索路径。我们将不在系统默认搜索路径下的库路径添加到该环境变量中即可。
跟PATH一致,当重新登录时,会恢复到默认路径。
(3)建立一个软链接
(4)将库路径保存到一个配置文件中
注意事项:
7、修改make文件,使动静态库都能形成
8、几个结论
(1)如果我们同时提供动态库和静态库,gcc默认使用的是动态库;
(2)如果我们非要使用静态库,需要使用static选项
(3)
(4)
六、理解动态加载
1、库默认就是一个磁盘级别的文件,当动态库加载之后,会被映射到进程地址空间的共享区中。
2、
3、