目录
作者和朋友建立的社区:非科班转码社区-CSDN社区云💖💛💙
期待hxd的支持哈🎉 🎉 🎉
最后是打鸡血环节:想多了都是问题,做多了都是答案🚀 🚀 🚀
最近作者和好友建立了一个公众号
公众号介绍:
专注于自学编程领域。由USTC、WHU、SDU等高校学生、ACM竞赛选手、CSDN万粉博主、双非上岸BAT学长原创。分享业内资讯、硬核原创资源、职业规划等,和大家一起努力、成长。(二维码在文章底部哈!)
静态库与动态库
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
- 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
- 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
- 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
- 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间
静态库
我们平时在Linux下的写法
生成静态库
ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)
归档文件:Archive files
r就是如果后面的.o更新了再重新打包就会更新.a
-L 指定库路径-l 指定库名测试目标文件生成后,静态库删掉,程序照样可以运行查看静态库中的目录列表
ar -tv libmymath.a
t: 列出静态库中的文件v:verbose 详细信息发布
动态库
生成动态库
shared: 表示生成共享库格式fPIC :产生位置无关码 (position independent code)库名规则: libxxx.so
动静态库合在一起写
使用动静态库
使用静态库
我们发现直接gcc是不行的
现在有三种解决办法
法一:法一是在当前路径查找头文件(就是啥也不做,全部都是自己在当前路径自己写的),也就是我们以前的写法(但是我们现在是把库和头文 件是并不在我们的可执行路径下的,而且以后使用的时候大部分也不会在)
法二:拷贝到系统路径下
因为以前我们是没有去使用第三方库的,我们一直用的是C/C++的库而gcc,g++默认就认识这两个库,所以不用告诉他们链接哪个库,而现在我们就需要自己去链接
(注意:库名命名时前面是lib后面是.a,而我们库名是去掉前缀和后缀剩下的,注意去掉是必须的,不然系统匹配就会失败)
我们自己链接就是 -l(链接) 选项带上 库名
但是现在不推荐这种写法,会污染系统的库
法三:-I -L -l
gcc mytest.c -o mytest -I ./lib-static/include/ -L ./lib-static/lib/ -lmumath
I(include):在预处理阶段找头文件
L(linke):在链接阶段找库在哪里
i:指是哪个库使用动态库
携带动态库不能运行程序的解决办法法一:拷贝到系统目录(一般指/usr/lib)(污染库,不推荐)
法二:和上面 -I -L -l 的一模一样(只多了最后一点)
但是
我们发现还运行不了
我们发现并没有依赖的动态库
是因为 -I -L -i 是gcc的选项,是告诉gcc的,所以形成了可执行程序
但是后面运行可执行程序是进程的事情,但是进程他也苦,他也不知道,所以运行不了那么为什么静态库没有这个问题呢?
是因为静态库形成可执行程序之后,已经把需要的代码拷贝进我们的代码中了,运行时,不 需要依赖你的库!(不需要运行时查找)
为什么动态库有这个问题?
那是因为程序和动态库是分开加载的!
如何解决上面的问题,也就是让他找到动态库即可!
法一:拷贝.so文件到系统共享库路径下, 一般指/usr/lib(也就是平常说的安装动态库)(不用这个)
法二:通过导入环境变了的方式 --- 程序运行的时候,会在环境变量中查找自己需要的动态 库路径 --- LD_LIBRARY_PATH
就可以了
但是如果我们退出登录,下次进去就没有了(说明是内存级的)法三:ldconfifig 配置/etc/ld.so.conf.d/,ldconfifig更新
cat /etc/ld.so.conf.d/bit.conf
这个路径就是表明系统里面如果你自己定义了动态库,那么除了在系统目录里面查找之外还 会在这个里面的配置文件里面查找
这每个配置文件里面就是一个路径![]()
ldconfig
就是让我们的配置文件生效。就是会把这个配置文件加载到系统对应的内存空间里,让我们 能找到它
而且关掉xshell之后再进去也是可以运行的!
法四:通过软连接的方式
就是在系统目录下建立了一个我们库的软连接
这个就是最简单的方法了
这样我们重新编译的时候
就可以只用指名头文件在哪里,至于库在哪里,是哪个库就不用关心了
所以说我们库里面有那么多软连接主要就是因为方便关于加载动态库
动态库的内容开始是在磁盘的,而我们的程序是在内存,当我们要使用动态库的内容的时候,是会把动态库的内容从磁盘通过页表映射到内存当中的共享区中,也就是说自己的代码和动态库的代码是分开的( fPIC),程序和动态库是分开加载的!然后运行就是两段代码来回跳转!加载动态库的时候,也是需要告知加载器动态库是在什么位置的,这也是为什么编译器编译的时候要知道共享库的位置,运行的时候我们又需要去添加共享库的位置!
最后的最后,创作不易,希望读者三连支持💖
赠人玫瑰,手有余香💖