🌈 个人主页:Zfox_
🔥 系列专栏:Linux
🦁 动静态库是可执行程序的“半成品”。
所有的库本质就是可重定向二进制文件的集合,即目标文件的集合,其中包含了大量的执行方法
使用ldd 可执行程序命令查看可执行程序依赖的动静态库文件
在 windows 中动态库以 .dll 为后缀,静态库以 .lib 为后缀。
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。
- 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间。
- 在Linux中动态库以.so为后缀,静态库以.a为后缀。库的命名有规范,一个库的名字去掉前缀lib,去掉后缀.so或者.a剩下的就是库的名字。例如libstdc++.so.6的库名字就是stdc++
- 在使用gcc/g++生成可执行程序的时候,默认情况下生成的可执行程序就是动态链接动态库,如果想要静态链接静态库的话,需要使用 - static选项来静态编译生成可执行程序。
- 浪费空间
- 占磁盘空间,因为静态链接是将静态库中的代码加载到可执行程序中,所以静态编译的文件自己体积比较大。
- 占内存空间,多个静态文件链接同一个静态库的时候,内存中会出现大量的重复代码
- 与库文件弱相关,不需要依赖库文件
- 由于静态编译的时候,已经将静态库中的代码都放到可执行程序的正文代码中了,所以可执行程序本身是一个独立的文件
- 与库文件强相关,必须依赖库文件
- 如果将一个动态库文件从内存和磁盘中删掉,这个动态库链接的可执行程序就都不能运行了
- 节省空间
- 节省内存空间,动态库文件在内存中只有一份,通过页表映射到不同进程的进程地址空间中的共享区共享。在静态链接的文件中,静态库的代码直接映射进了进程地址空间的正文代码中。
🦁 我们在给被人静态库的时候,需要把 .a/.so 库文件和 .h 头文件给到对方。.a/.so 让别人可以调用库中的函数,.h 告诉别人库中有哪些函数可以被调用,相当于函数使用的说明书。
- 在使用第三方库的时候,需要指明库的名称
🦁 假设有四个文件 my_stdio.c my_stdio.h my_string.c my_string.h,我们需要通过它们制作一个动静态库。
main.c
my_stdio.h
my_stdio.c
my_string.h
my_string.c
Makefile
- 编译同名的目标文件
- 生成静态库
- 生成一个叫做 mystdio 的静态库需要使用 ar 命令,其中 -r 选项表示 replace,-c 表示 create
- mystdio 静态库前后需要加上lib和.a,使用的时候需省略
🥝 1.安装到系统里面
🥝 2.手动调用我们自己的静态库
调用的函数的库文件在哪
- 使用 -L + 库文件的路径(告诉编译器,在我指明的路径下找)
调用的库的名称
- 使用 -l + 库的名称

🥝 3.使用带路径的库
- 此时我们使用 makefile 将头文件和库文件分门别类放在 stdc 的目录下
💦 调用的函数的头文件在哪
💦 调用的函数的库文件在哪
💦 调用的库的名称

- 生成目标文件
在生成同名的目标文件的时候,需要加上-fPIC选项,即产生与位置无关码,这样就可以让可执行程序找到对应的动态库。
- 生成动态库
在打包动态库的时候,需要加上 -shared 选项形成库文件
🥝 1.安装到系统里面

🥝 2.手动调用我们自己的动态库
当我们有了头文件和库文件的时候不安装到系统里
调用的函数的库文件在哪
- 使用 -L + 库文件的路径(告诉编译器,在我指明的路径下找)
调用的库的名称 - 使用 -l + 库的名称

🥝 3.使用带路径的库
- 此时我们使用 makefile 将头文件和库文件分门别类放在stdc的目录下
💦 调用的函数的头文件在哪
💦 调用的函数的库文件在哪
💦 调用的库的名称

🦁 这里也是需要特别注意:当运行可执行文件时,我们会发现找不到动态库 。这也就是动态库的特别之处,上述步骤跟静态库操作几乎一样,这里开始就发生转折。
Ubuntu 自身系统设定的相应的设置的原因,即其只在 /lib and /usr/lib 下搜索对应 的.so 文件,故需将对应 so 文件拷贝到对应路径。 centos则是 /lib/64
- 在 /lib/ 下建立软链接
- 使用的时候需要导入.so动态库的路径 export LD_LIBRARY_PATH=
这里有需要注意:添加环境变量后,默认只在本次登录有效,下次登录时无效(默认清理登录前一次添加环境变量)。
- 直接拷贝动态库到系统目录下 /lib/64 /usr/lib64
- 在 目录下建立自己的 的配置文件,把动态库的路径放进去,然后
- 命令用于更新共享库的缓存。你需要运行此命令以使新的配置文件生效。
静态库不需要加载
这个过程,在磁盘中 main.c 和 lib.c-库,会先在磁盘中形成一段代码,然后对这段代码进行编译,编译的本质就是预处理,编译-查找错误,形成二进制代码,然后进行汇编形成二级制指令。在编译阶段的时候就已经形成了虚拟地址空间。在虚拟地址空间中,这段代码也就被存入代码区,这个是根据不同区的特性所决定的。当执行这段代码的时候,操作系统就会直接在代码区进行访问。

动态库加载
🦁 动态库加载的过程,在磁盘中有一个 my.exe (可执行)和 lib.so(动态库),在形成可执行之前,编译阶段时,我们用到了 fPIC :产生位置无关码。
在这个阶段,动态库会将指定的函数地址,写入到可执行文件中。这个地址可以理解成 my_add.c (地址) + 偏移地址。
形成好可执行文件之后,磁盘将可执行文件拷贝到内存中,内存通过页表映射到虚拟地址空间的代码区中,当 OS 执行程序时,扫描到 my_add.c 是需要调用动态库的时候,程序会停下来,OS 会再通过函数的地址,然后页表映射去内存到磁盘中找动态库中,找到后拷贝到内存,又通过页表映射到共享区中。OS 再去共享区调用该方法,然后向下执行程序。
以上就是我对 的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉

版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/11993.html
