当前位置:首页 > 实用技巧 >

指令关系是动态还是静态(前固定指令后固定指令的区别)

来源:原点资讯(m.360kss.com)时间:2024-01-16 03:24:59作者:YD166手机阅读>>

作为一名C/C 程序员,对于编译链接的过程要了然于胸。首先大概介绍一下,编译分为3步,首先对源文件进行预处理,这个过程主要是处理一些#号定义的命令或语句(如宏、#include、预编译指令#ifdef等),生成*.i文件;然后进行编译,这个过程主要是进行词法分析、语法分析和语义分析等,生成*.s的汇编文件;最后进行汇编,这个过程比较简单,就是将对应的汇编指令翻译成机器指令,生成可重定位的二进制目标文件。以上就是编译的过程,下面主要介绍两种链接方式--静态链接和动态链接。

静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时,下面来详细介绍这两种链接方式。

一、静态链接

1.为什么要进行静态链接

在我们的实际开发中,不可能将所有代码放在一个源文件中,所以会出现多个源文件,而且多个源文件之间不是独立的,而会存在多种依赖关系,如一个源文件可能要调用另一个源文件中定义的函数,但是每个源文件都是独立编译的,即每个*.c文件会形成一个*.o文件,为了满足前面说的依赖关系,则需要将这些源文件产生的目标文件进行链接,从而形成一个可以执行的程序。这个链接的过程就是静态链接

2.静态链接的原理

由很多目标文件进行链接形成的是静态库,反之静态库也可以简单地看成是一组目标文件的集合,即很多目标文件经过压缩打包后形成的一个文件,如下图,使用ar命令的-a参数查看静态库的组成:

指令关系是动态还是静态,前固定指令后固定指令的区别(1)

以下面这个图来简单说明一下从静态链接到可执行文件的过程,根据在源文件中包含的头文件和程序中使用到的库函数,如stdio.h中定义的printf()函数,在libc.a中找到目标文件printf.o(这里暂且不考虑printf()函数的依赖关系),然后将这个目标文件和我们hello.o这个文件进行链接形成我们的可执行文件。

指令关系是动态还是静态,前固定指令后固定指令的区别(2)

这里有一个小问题,就是从上面的图中可以看到静态运行库里面的一个目标文件只包含一个函数,如libc.a里面的printf.o只有printf()函数,strlen.o里面只有strlen()函数

我们知道,链接器在链接静态链接库的时候是以目标文件为单位的。比如我们引用了静态库中的printf()函数,那么链接器就会把库中包含printf()函数的那个目标文件链接进来,如果很多函数都放在一个目标文件中,很可能很多没用的函数都被一起链接进了输出结果中。由于运行库有成百上千个函数,数量非常庞大,每个函数独立地放在一个目标文件中可以尽量减少空间的浪费,那些没有被用到的目标文件就不要链接到最终的输出文件中。

3.静态链接的优缺点

静态链接的缺点很明显,一是浪费空间,因为每个可执行程序中对所有需要的目标文件都要有一份副本,所以如果多个程序对同一个目标文件都有依赖,如多个程序中都调用了printf()函数,则这多个程序中都含有printf.o,所以同一个目标文件都在内存存在多个副本;另一方面就是更新比较困难,因为每当库函数的代码修改了,这个时候就需要重新进行编译链接形成可执行程序。但是静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快。

二、动态链接

1.为什么会出现动态链接

动态链接出现的原因就是为了解决静态链接中提到的两个问题,一方面是空间浪费,另外一方面是更新困难。下面介绍一下如何解决这两个问题。

2.动态链接的原理

动态链接的基本思想是把程序按照模块拆分成各个相对独立部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是像静态链接一样把所有程序模块都链接成一个单独的可执行文件。下面简单介绍动态链接的过程:

假设现在有两个程序program1.o和program2.o,这两者共用同一个库lib.o,假设首先运行程序program1,系统首先加载program1.o,当系统发现program1.o中用到了lib.o,即program1.o依赖于lib.o,那么系统接着加载lib.o,如果program1.o和lib.o还依赖于其他目标文件,则依次全部加载到内存中。当program2运行时,同样的加载program2.o,然后发现program2.o依赖于lib.o,但是此时lib.o已经存在于内存中,这个时候就不再进行重新加载,而是将内存中已经存在的lib.o映射到program2的虚拟地址空间中,从而进行链接(这个链接过程和静态链接类似)形成可执行程序。

3.动态链接的优缺点

动态链接的优点显而易见,就是即使需要每个程序都依赖同一个库,但是该库不会像静态链接那样在内存中存在多分,副本,而是这多个程序在执行时共享同一份副本;另一个优点是,更新也比较方便,更新时只需要替换原来的目标文件,而无需将所有的程序再重新链接一遍。当程序下一次运行时,新版本的目标文件会被自动加载到内存并且链接起来,程序就完成了升级的目标。但是动态链接也是有缺点的,因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失。

据估算,动态链接和静态链接相比,性能损失大约在5%以下。经过实践证明,这点性能损失用来换区程序在空间上的节省和程序构建和升级时的灵活性是值得的

4.动态链接地址是如何重定位的呢?

前面我们讲过静态链接时地址的重定位,那我们现在就在想动态链接的地址又是如何重定位的呢?虽然动态链接把链接过程推迟到了程序运行时,但是在形成可执行文件时(注意形成可执行文件和执行程序是两个概念),还是需要用到动态链接库。比如我们在形成可执行程序时,发现引用了一个外部的函数,此时会检查动态链接库,发现这个函数名是一个动态链接符号,此时可执行程序就不对这个符号进行重定位,而把这个过程留到装载时再进行。

栏目热文

基本指令和功能指令的区别(指令和命令的主要区别是什么)

基本指令和功能指令的区别(指令和命令的主要区别是什么)

在PLC的编程语言中,最简单的就是图形语言,如我们所学的梯形图与SFC,这两者在编程软件中都属于简单工程。而我之前所分享...

2024-01-16 02:38:39查看全文 >>

直接指令和间接指令的区别(什么是直接指令和非直接指令)

直接指令和间接指令的区别(什么是直接指令和非直接指令)

我们都知道西门子200plc有三种寻址方式:立即寻址、直接寻址、间接寻址;这里主要给大家区分下直接和间接寻址1、直接寻址...

2024-01-16 03:16:17查看全文 >>

典型指令的分类和各自的特点(指令性指令和伪指令的区别)

典型指令的分类和各自的特点(指令性指令和伪指令的区别)

一.三菱CPU模块的指令类型包括顺控指令、应用指令等。其中顺序指令主要包括:触点指令、连接指令、输出指令、边沿脉冲指令、...

2024-01-16 02:38:00查看全文 >>

广义指令是用什么来执行的(广义指令)

广义指令是用什么来执行的(广义指令)

关注我!操作系统概述1.1 知识要点总结一、操作系统的概念、特征、功能和提供的服务1.操作系统的概念(1)操作系统定义操...

2024-01-16 02:49:09查看全文 >>

指令和伪指令区别并举例说明(复杂指令和精简指令具体区别)

指令和伪指令区别并举例说明(复杂指令和精简指令具体区别)

单片机是无法识别汇编语言程序的,所以用汇编语言写好程序后,还要用汇编程序将汇编语言程序(以下称作源程序)汇编(翻译)成...

2024-01-16 02:45:22查看全文 >>

简述指令和伪指令的区别(指令语句与伪指令语句的异同点)

简述指令和伪指令的区别(指令语句与伪指令语句的异同点)

五、计算机控制为了提高滤波性能,常采用模拟和数字滤波相结合的方法,请举例说明数字滤波的方法有哪些?答:数字滤波,就是通过...

2024-01-16 03:03:49查看全文 >>

处女座是所有星座中最好的吗

处女座是所有星座中最好的吗

导读:星座很多人会看,还会看每个星座的特点,有些星座公认的好性格,容易相处,但也有些星座出了名的难搞,千万不要去招惹才好...

2024-01-16 03:00:25查看全文 >>

处女座是最特别的星座(处女座是不是最好的星座)

处女座是最特别的星座(处女座是不是最好的星座)

处女座,这个星座本身就充满了神秘和魅力。他们有着独特的性格特点,聪明、细腻、追求完美,这些特质使得处女座成为十二星座中最...

2024-01-16 02:52:34查看全文 >>

处女座在哪个星座里最好(处女座和哪个星座最好相处)

处女座在哪个星座里最好(处女座和哪个星座最好相处)

处女座是黄道十二宫中最有爱心、最富有同情心和最可靠的星座之一,这使得处女座灵魂伴侣的星座成为占星术中最幸运的星座之一。处...

2024-01-16 02:47:19查看全文 >>

处女座是最完美的星座吗(处女座是很厉害的星座)

处女座是最完美的星座吗(处女座是很厉害的星座)

Top3处女座处女是完美星座的小先锋做人做事从来都是干净漂亮无论是生活还是工作Ta总是力争上游你会发现Ta很少与烂人烂事...

2024-01-16 03:02:44查看全文 >>

文档排行