计算机的库是干什么的

库,这个为什么会存在,它的存在一定具有它的合理性。

库这个概念和程序的运行是分不开的,一个简单的helloword程序,经过编辑,预处理,编译,汇编,链接。然后系统调用输出在命令行窗口上。

汇编这一步生成的是可执行可链接文件(ELF),这个程序调用了printf函数,所以是链接器把main.o文件和printf所在的printf.o文件链接在一起生成的。

一个程序必然使用很多函数,如果把所有的函数定义放在一个.c文件,把这些函数所有的声明放在一个.h文件,到时候直接添加该.h文件也许可以,我是这

样做过,但是这样对于大型项目的开发很不好,一个是所有的函数都在一个.c文件生成的目标文件肯定非常大,而且每次都要把这个.c文件拷贝到工程所在的目录下面

麻烦,而且有些标准函数是不应该更改的,这些标准函数对每个C程序都是通用的,总之很麻烦。

如果不使用静态库有两种方法对用户提供这些函数:

1.一种方法是让编译器直接辨认出对标准函数的调用,并且直接生成相应的代码,但是这种方法对应C语言不合适,因为标准函数太多,会给编译器增加复杂性,每次增加或者删除修改一个函数,就要一个新的编译器版本。对编译器开发人员很复杂。

2.把所有的标准C都放在一个单独的可重定位的目标模块里面,应用程序员可以把这个模块链接到可执行文件里面

优点:标志函数的实现和编译器没有关系。

缺点:系统的每个可执行文件都包含一份标准函数集合的完整拷贝,浪费磁盘空间。

   对于任何函数不论多么小的改变,都要重新编译整个源文件,非常浪费时间。这种方法和刚开始提到的有点类似。

3.可以为每个标准函数建立一个可重定位文件,放在大家都知道的目录。

优点:克服了方法2的缺点

缺点:自己要显示的链接合适的目标模块到他们的可执行文件里面,非常容易出错,比如:gcc main.c /usr/lib/printf.o /usr/lib/scanf.o /usr/lib/gets.o 

为了更好的解决上述问题:静态链接库应运而生

相关的函数可以被编译为独立的目标模块,然后封装成一个单独的静态库文件,应用程序可以通过命令行窗口上单独指明文件名字来使用这些在库里面定义的函数。

在链接时,链接器只会拷贝程序所引用的目标模块,减少了可执行文件的磁盘和存储器的大小。在unix里面静态库以存档的特殊文件格式存在与磁盘里面,存档文件是一组连接起来的目标文件的集合,有一个头部用来描述每个成员目标文件的大小和位置,存档的后缀名.a。


静态链接库固然解决了很多问题,但依旧有不足之处

1.静态库也需要定期的维护和更新,如果程序员想把自己的库更新到最新版本,他必须以某种方式了解到该库的更新情况,然后显示的将他们的程序和更新了的库重新链接。

2.几乎每个C程序都会使用printf 和scanf函数,这些函数的代码会被复制到每个运行进程的文本段,造成存储器系统资源的极大浪费。

为了解决以上两个主要问题,动态链接共享库应运而生。

共享库是一个目标模块,运行时可以加载到任意的存储器地址,并和一个在存储器中的程序链接起来,由系统调用一个动态连接器的程序实现。贡献库以.so 为后缀

共享库以两种不同的方式共享:

1.对于一个库只有一个.so文件,所有引用该库的可执行目标文件共享这个.so文件的代码和数据,而不是像静态链接库把内容拷贝和嵌入到他们的可执行文件里面。

2.存储器,一个共享库的.text节的一个副本可以被不同的正在运行的进程共享.

动态链接大体过程是静态先执行一些链接,链接的是共享库的重定位和符号表信息,然后加载器加载的时候,在存储器里面完全链接可执行文件。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值