✨道路是曲折的前途是光明的 专注C/C、Linux编程与人工智能领域分享学习笔记 感谢各位小伙伴的长期陪伴与支持欢迎文末添加好友一起交流一、基础背景二、动态库的制作三、动态库的使用四、总结一、基础背景一些动静态库的基础知识和静态库的制作与使用的讲解请点击【Linux】库制作与原理一静态库的制作与使用二、动态库的制作我们静态库实现的是一个加法的使用我们动态库的演示就来一个减法和乘法吧我们需要用要的两个源文件sub.cmul.c两个头文件sub.hmul.h。#pragmaonceexternintmy_sub(intx,inty);#includesub.hintmy_sub(intx,inty){returnx-y;}#pragmaonceexternintmy_mul(intx,inty);#includemul.hintmy_mul(intx,inty){returnx*y;}其制作与静态库有些类似但是所用的选项和打包工具是不同的我们先看Makefile自动化构建里面的代码再来介绍一下不同之处。lib libmymath.so $(lib):sub.o mul.o gcc -shared -o $ $^ sub.o:sub.c gcc -fPIC -c $^ -o $ mul.o:mul.c gcc -fPIC -c $^ -o $ .PHONY:clean clean: rm -rf *.o *.so mylib .PHONY:output output:$(lib) mkdir -p mylib/include mkdir -p mylib/mathlib cp *.h mylib/include cp *.so mylib/mathlib具体的注释请看上一篇文章静态库的制作与使用这里我们只看不同点。我们这里看到gcc指令多了一个-fPIC这个是用来产生位置无关码形成动态库的时候-shared这个是专门用来形成.so后最的动态库文件指令执行我们自动化构建工具的指令我们先通过ls看一下权限.其实是因为动态库如 libmymethod.so的可执行权限x并非指其能被直接运行而是因为可执行程序本身具备可执行权限在运行时会跳转调用动态库中的函数逻辑因此动态库的 x 权限本质是为了支撑可执行程序对其函数的调用执行是一种 “间接的可执行能力”。注意静态库无需加载且无可执行权限x因为静态库在链接阶段会将所需函数代码直接拷贝到可执行程序中拷贝完成后静态库即完成使命其代码成为可执行程序的一部分最终运行时可执行程序直接在自身内存空间执行这些代码无需跳转至静态库因此静态库既无需加载也不需要可执行权限x可执行程序也不再依赖静态库。三、动态库的使用我们此时站在用户的角度使用我们制作的动态库首先要准备好自己的测试文件test.c下面再写然后把我们提供的动态库目录mylib移动到测试目录下以此模拟用户下载并存放库文件的操作。#includestdio.h#includesub.h#includemul.hintmain(){inta20;intb10;intcmy_sub(a,b);intdmy_mul(a,b);printf(a - b %d\n,c);printf(a * b %d\n,d);return0;}和静态库一样我们这里gcc时候直接带上-I,-L,-l指令我们发现并没有静态库的使用那么简单当有了可执行程序文件我们执行的时候还是失败了它找不到我们的共享库即使这里我们告知了动态库所在的路径以及哪一个动态库这是为什么因为编译时指定路径 ≠ 运行时能找到库这也是动态库比静态库复杂的根本原因。编译链接阶段和运行加载阶段是完全独立的两个过程编译器的工作只到 “生成可执行程序a.out/test” 为止它不会把 “动态库的路径” 写入可执行程序中。那么该如何解决这种问题法一把动态库拷贝到系统目录下sudo libmymath.so /usr/local/libsudo ldconfig此时我们我们在运行./a.out我们先删除一下上面拷贝到系统下的库,然后同样的刷新缓存一下发现又找不到了说明删除成功sudo rm /usr/local/lib/libmymath.so法二在系统默认路径下建立软链接这里建议使用绝对路径避免成为无效链接。sudo ln -s /home/dh/study/2-4/libmymath.so /usr/local/lib/libmymathsudo unlink /usr/local/lib/libmymath.so直接删除我们的软链接法三更改LD_LIBRARY_PATH,也就是把自己库所在的路径添加到环境变量里边export LD_LIBRARY_PATH$LD_LIBRARY_PATH:XXXXX这个export命令是临时生效的 —— 关闭当前终端、重启电脑或新开终端后LD_LIBRARY_PATH会变回空。法四配置/etc/ld.so.conf.d在这个路径下新建自己的动态库路径配置文件然后刷新缓存删除的话只要我们缺到在上面的路径下直接执行rm即可四、总结本文详细介绍了Linux下动态库以libmymath.so为例的制作与使用制作时需准备功能源文件sub.c/mul.c和头文件sub.h/mul.h通过gcc -fPIC生成位置无关码、-shared打包为动态库并用Makefile自动化构建整理文件。使用时需用-I/-L/-l指定头文件和库路径但动态库编译时指定路径不等于运行时能找到核心原因是编译与运行阶段相互独立。需通过“拷贝库到系统目录刷新缓存”“建立软链接”“设置LD_LIBRARY_PATH环境变量”“配置/etc/ld.so.conf.d目录”四种方法解决。相比静态库动态库需依赖外部文件、有间接可执行权限、可共享节省空间且更新方便而静态库链接后无依赖、无x权限两者各有优劣实操中需根据需求选择合适方式。