【Linux】动态链接和静态链接

 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而 没有定义函数的实现,那么,是在哪里实“printf”函数的呢? 作为一名C/C++程序员,对于编译链接的过程要了然于胸。首先大概介绍一下,编译分为3步,首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件;然后进行编译,这个过程主要是进行词法分析、语法分析和语义分析等,生成*.s的汇编文件;最后进行汇编,这个过程比较简单,就是将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件。以上就是编译的过程,下面主要介绍两种链接方式--静态链接和动态链接。静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时。 最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到 系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。

1.动态链接

    在编译的时候不直接拷贝可执行代码,而是通过 记录一系列符号和参数,在程序运行或加载时将这些信息传递给操作系统,操作系统负责将需要的动态库加载到内存中,然后程序在运行到指定的代码时,去共享执行内存中已经加载的动态库可执行代码,最终达到运行时连接的目的。

8429f55e0fdf449294f807eb6830c5bd.png

 file探测gcc编译的文件的类型,发现mytest.c是动态链接的

a3cba0a6c8634715b04d0f4e6b2eff81.png

表明这个可执行程序是依赖/lib64/libc.so.6这个库的,库的地址是0x00007f7706feb000

 在linux下库的分类:

1.动态库:libXXXXX.so(默认使用的库)

2.静态库:   libXXXXX.a

库的名称是去掉前缀和后缀就是库的名称

所以我们的可执行文件的库的名称是c (c标准库)

 优点:生成的可执行的程序小,节省资源(内存、网络)

缺点:库升级或者库被删除受到影响

2.静态链接

     在生成可执行文件的时候(链接阶段),把所有需要的函数的二进制代码都包含到可执行文件中去。因此,链接器需要知道参与链接的目标文件需要哪些函数,同时也要知道每个目标文件都能提供什么函数,这样链接器才能知道是不是每个目标文件所需要的函数都能正确地链接。如果某个目标文件需要的函数在参与链接的目标文件中找不到的话,链接器就报错了。目标文件中有两个重要的接口来提供这些信息:一个是符号表,另外一个是重定位表。

生成静态链接的可执行文件 :

6b4b16fa39624f5a82bf4e567732d9f3.png

 查看文件的属性是statically linked 静态链接的:

12f27d8f3ba74406ae5d173ab7cac7f6.png

ll查看所有文件:

778b456ee8f34cfc872a95518cbdfb6b.png

查看两个文件的大小发现静态链接的可执行文件test的大小要比动态链接生成的文件mytest.c大小要大得多这也就是静态链接的缺点。

优点:不受库升级或者库删除受到的影响

缺点:形成的可执行程序体积过大

3.其他

一般来说Linux系统会自带动态库,而静态库需要自己下载

sudo yum install glibc-static

动态链接------>动态库

静态链接------>静态库

动态链接不能访问静态库,静态链接不能访问动态库

头文件是可读的文本,而库文件是一些不可读的二进制文件,头文件是起到函数,变量类型定义的作用,函数的具体实现在库里,变量的定义在.c文件里
编译器会根据头文件进入相关目录查找库中是否有实现

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bite-ccc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值