火影 发表于 5 天前

Linux动态库和静态库

1,手动制作静态库

1,如何形成静态库文件

做库时,头文件(.h)必须暴露,源文件(.c)必须隐藏。
操作:将必要形成库的文件编译成.o文件:
https://i-blog.csdnimg.cn/direct/ab3ce7fdf05e4c99a51eea35f7dc18f2.png
然后用指令:ar -rc libmy_stdio.a my_stdio.o my_string.o
其中,如果形成库文件前缀必须是lib,后缀必须是.a,后面可以加版本号。
https://i-blog.csdnimg.cn/direct/40a25b08c5a94e7ca17ffb2c608bfb8e.png
这时间就可以把头文件和库文件交给另外一个人使用。
2,如何使用静态库

a,在系统层面导入库文件

起首拿到别人给的头文件和库文件,我们必要去系统路径下安装别人给的头文件和库文件:
安装头文件:sudo cp*.h /usr/include/
安装库文件:sudo cp libmy_stdio.a /lib64/
https://i-blog.csdnimg.cn/direct/5f46f341bc384639b42dd3a2ade6940c.png
这个时间在c文件里包头文件就可以找得到库文件:
                  https://i-blog.csdnimg.cn/direct/a91690069da54a2b8ec113ad3632f63a.png
下面编译一下使用别人库函数的文件:
https://i-blog.csdnimg.cn/direct/916d5b3a86684fc683799a65fb15423f.png
这个时间发现会报错,因为gcc只认自己的标准库,我们写的库属于第三方文件,gcc不认识,这时间要让gcc找到可以用指令:
gcc main.c -l my_stdio(留意!!!这里要去掉库文件的前缀和后缀)
https://i-blog.csdnimg.cn/direct/60475528d4d443f4b125b2f1ab5165e6.png
可以看到这时间编译乐成!以是我们学到了gcc的一个新指令 -l,引入指定名称的第三方库名称
b,如果头文件和库文件在同一目录下怎么使用

我们先把之前我们导入系统中库文件删除:
rm  /usr/include/my_*
rm /lib64/libmy_stdio.a
https://i-blog.csdnimg.cn/direct/5db85f4eb05e491595fe56f3634d41d4.png
这时我们用gcc main.c -o main会发现程序无法编译:
https://i-blog.csdnimg.cn/direct/c0145d47f6b941988bd54d032100600b.png
可以看到系统根据c中写的头文件找不到库文件,此时在与它同名文件夹下有库函数文件。
这时用gcc main.c -o mian -lmy_stdio会发现也不行:
https://i-blog.csdnimg.cn/direct/94bfb7e2a6de46f8832d057933096c58.png
以是得出一个结论,gcc在查找静态库时不会在当前路径下查!
这个时间可以引入gcc的另一个指令:-L(告诉编译器,编译时查找库在指明的路径下找)
操作:gcc main.c -o main -L. -lmy_stdio
https://i-blog.csdnimg.cn/direct/4e8c65e70bf64d61a46adb41ab6cfd6a.png
这时乐成在同文件下使用静态库
c,如何封装Makefile和怎么发布静态库

起首完成.o文件的编译,然后形成库文件:
https://i-blog.csdnimg.cn/direct/0d2f1a9b0d2f4a67a114b6a2439ac91f.png
再将c文件依次编译成.o文件:
https://i-blog.csdnimg.cn/direct/7607255e75ed49ea8e7e092b0e5bdb4d.png
如许就可以自动形成库:
https://i-blog.csdnimg.cn/direct/230626e3f66c42a1ae028dd8aff2a592.png
那么我们怎么发布?
这里引用一个小知识,再makefile中也是可以调用系统接口的:
https://i-blog.csdnimg.cn/direct/b945d487dbfc4c3e981cb2a077b4c732.png
https://i-blog.csdnimg.cn/direct/ec8359d1e8fc4a34b00d9d838f50d6d7.png
这个时间就可以将写好的stdc压缩然后发给别让人用。那么假设我就是那个别人,那么我该怎么用别人打包好的库文件?
gcc指令中-I可以去指定路径下寻找头文件:
gcc main.c -I stdc/include -Lstdc/lib -lmy_stdio
https://i-blog.csdnimg.cn/direct/849e13c880414315b57b68c3084f0ad6.png
https://i-blog.csdnimg.cn/direct/fc50eb46286642289edfa9fd2df29656.png
2,如何手动制作动态库

1,如何形成动态库文件?

在前面章节中已经相识了静态库怎么创建,那么动态库和静态库的创建方式雷同,我们直接在makefile中修改:(留意,动态库的后缀是.so)
gcc中加入-shared,可以告诉gcc不要形成可执行程序,帮我形成so库
https://i-blog.csdnimg.cn/direct/a8ae9445ed1f4a739b071cdea4ac6715.png
这个时间make一下:
https://i-blog.csdnimg.cn/direct/69aedf2566d544ffa18efa44b377e360.png
可以看到里面多了一个库函数文件,使用方法就是和之前一样把头文件和库文件分别拖进系统中的include和lib64文件夹中,就可以直接:
gcc main.c -lmy_stdio就可以直接运行这里就不做展示。
2,如何使用动态库

a,当动态库与main .c同文件

gcc main.c -o main -L. -lmy_stdio
https://i-blog.csdnimg.cn/direct/bfd653e6dede438ba1d87145ec363984.png
https://i-blog.csdnimg.cn/direct/68fd89cefb13470dacabab9fef683fa0.png
讲一个系统指令:ldd,可以用来查可执行程序依赖哪些程序
https://i-blog.csdnimg.cn/direct/fc69c410fcd74604a8fb4cea21febe70.png
可以看到main可执行程序依赖这个库文件,
如果把库删了:
https://i-blog.csdnimg.cn/direct/205aafa4a17847899eecd6cf7045fc3b.png
就会显示找不到库文件。
3,发布动态库

流程和静态库一样:
https://i-blog.csdnimg.cn/direct/be4ee2f3a47640c8a2eceab39a8de46c.png
https://i-blog.csdnimg.cn/direct/e33b230ee85a4ed08884cd8a3fca4dca.png
https://i-blog.csdnimg.cn/direct/234c13f2d1504f99b4663921c533f4b4.png
但是这个时间gcc main.c -o main -I stdc/include -Lstdc/lib -lmy_stdio:
https://i-blog.csdnimg.cn/direct/e2aa8c0fc95244c9aec53e3790355702.png
会发现形成的main执行不了:
https://i-blog.csdnimg.cn/direct/148d99c06611495992bc5df0bbbf7708.png
会发现他的ldd为空,这时因为在main运行的时间与gcc没有关系,gcc找到了链接文件不代表可执行文件找到了,os要加载你对程序,但是系统找不到动态库。
4,如何给系统指定路径找动态库

1,拷贝到默认路径下(前面已强调多次)

2,建立软链接:

sudo ln -s /路径/库名 /lib64/同名.so就可以建立软链接:
https://i-blog.csdnimg.cn/direct/57ddda27095f4ec383f5a1deb9654892.png
https://i-blog.csdnimg.cn/direct/9ba7f238231c4bf6988fa400361f4fbd.png
这时就可以运行程序。
3,Linux系统中,os可以根据环境变量查动态库

这个时间可以用:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: +路径也可以:
如果想永久加env可以vim .bash.src中加入export ....
4,讲路径写到.conf文件里

https://i-blog.csdnimg.cn/direct/c9ad81f246944d1faf2f8506030cb2aa.png
touch /etc/ld.so.conf.d/2024.conf
https://i-blog.csdnimg.cn/direct/1ca163fc680f4ec88ae99eb7e9dad38c.png
这时将库的路径写道2024.conf中:
https://i-blog.csdnimg.cn/direct/5c2c288009504692a608237382dbd229.png
然后必要用到指令ldconfig加载一下:
https://i-blog.csdnimg.cn/direct/7e525cb6d5b843a39a1a46303d6a666e.png
其中1方法和3方法比力常用,如果同时提供了so a文件呢?
gcc,g++会默认使用动态库,如果必要他只用静态库,可以加-static
https://i-blog.csdnimg.cn/direct/5cd32c4d7fa94fb0bf032fb81f5efc5a.png
这时去掉路径中的.so和-static:
https://i-blog.csdnimg.cn/direct/ec7f40a696c043d2b14f7b2ef9ba10aa.png
https://i-blog.csdnimg.cn/direct/c0cebc8a003144f9ac440639871a6645.png
可以跑?为什么?
如果只提供静态库,但是链接方法是静态库请见下篇分晓。
5,原理上明白动态库

我们知道,在堆区和栈区直接有一个共享区:
历程在执行库的方法,是在自己的地点空间中跳转运行

                                                                     https://i-blog.csdnimg.cn/direct/d7cd530aaa9f46229cd161d15ec15626.png
然后动态库他是从磁盘加载到内存中通过页表的映射到共享区给代码使用。
                                                        https://i-blog.csdnimg.cn/direct/ab73f7ee3d39441ba2f3bcd88dcae1aa.png
这个时间如果有其他程序也必要调用这个库,就直接从页表映射到内存中找库:
https://i-blog.csdnimg.cn/direct/4c31660712a041b4815aeb27ca31a715.png










免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Linux动态库和静态库