提前祝大家新春快乐!

上一节说了静态库,这一节说下动态库,然后再说下两者的区别,让你一次搞定这个玩意。

我们先看代码,这里只是用了add,没有输出结果,但不影响我们演示,看代码:

我们把add.c编译成so库,gcc -fPIC -shared add.c -o libadd.so ,这里关键点就是PIC这个参数,以及shared ,PIC代表的是生成与位置无关代码,这里我们来举例说下大家就明白了。

加入100位置需要找60位置的数据,那么可以是获取60位置的数据,还有一种是获取100-60也就是偏移40位置的数据。用偏移之后,那么不管这段代码放到哪个位置,都是一致的,因为相对位置不变,但是绝对位置是变化的。

所以动态库是需要这个参数的,当前gcc优化,静态库,可执行文件,动态库,都默认要求使用-fPIC ,让保持相对寻址。

-shared ,指明生成的是动态库。

然后我们编译gcc -o hello hello.c -L./ -ladd 

运行时候会报错,会提示我们找不到so,这里就是很特别的地方,动态库是不链接进入我们的hello可执行文件的,只是给hello可执行文件查找,给出它这里有,你按照这个编过就可以了。

真正执行的时候,系统会从默认位置去找,找不到就报错了。我们可以使用export LD_LIBRARY_PATH=./ ,来进行指定,让运行的时候,可以从当前目录去找对应的so库,最终执行成功。

下来我们说下编译成静态库的libadd.a 和libadd.so 这两个最终在hello的表现,静态库出来的hello比动态哭出来的大了20字节,这个字节主要是add函数实现的占用大小。

这也是静态库和动态库的本质区别:静态库链接的时候会进入可执行文件中,而动态库不会。静态库的优势就是,可执行文件生成后,就不需要这个.a可以删除,但是动态库是需要跟着一起存在,因为动态库里面的方法,实际没有在可执行文件里面。

这样子就有个优势,如果多个可执行文件编译时候依赖静态库,那么如果静态库修改后,相关的可执行文件都需要重新链接,进行修正。但是如果是动态库的话,只需要生成新的动态库就可以,可执行文件不需要重新链接。

而关于动态库,系统还提供了动态加载的机制,我们来看下。

核心就是 dlopen 打开动态库, dlsym 找到对应的符号, 调用它,然后最终关闭dlclose。是不是发现很简单?

编译的时候,要记住把对应的库依赖进来,否则会发现这些符号找不到。我们说过include只是说这些函数声明,让编译的时候按照声明去编译,到最后链接的时候,要去找这写的实现地方。

这几个的实现是在libdl.so里面,所以我们编译是 gcc -o hello hello.c -ldl,然后运行就可以了。如果想深入学习动态库的加载,下载glibc源码,即可查看相关代码。

我们要多去看开源项目,这里分享一点,开源项目会有很多神奇的用法,比如

     __attribute__ ((p (".init_array"), aligned (sizeof (void *))))

这个指定了数据是在init_array 这个段里面,同时依据指针大小对其,这个有什么好处呢?主要是可以将一堆相关的数据,通过这个属性,让它们归类到一起,方便系统检索到,进行调用。

我们先把这个悬念留下来,这个牵扯到另一个知识点,就是链接器脚本,感兴趣的可以先百度学习下,随后我们讲下这块知识。好了,这一节就说到这里,下一节我们说下,printf的声明,可变参数的实现,以及如何使用。

喜欢,帮忙转发~~

~~ end not end ~~

热门文章

零基础新手自学Python编程教程入门精通学习资料网站大全

自学编程C语言不迷路,我私藏的书单分享给你!

零基础新手学习算法Leetcode刷题指南

程序员码农IT工程师自学编程计算机入门进阶学习网站大全

程序员面试题宝典以及相关书籍下载!

计算机类常用电子书整理大全

职场老鸟,互联网十年从业生涯,分享 [Java,Python,安卓,AI,爬虫] 技术文章,学习资料, 热点趣闻等。关注回复 1024 Python 电子书大全 面试资料,给你一份私藏的程序员好礼,永远更新中!赶紧来关注哦!

我的微信 code_gg_boy 。

更多推荐

C语言.so如何把它推倒?这两种玩法足够一辈子!