静态库和动态库系列(1)
最近一个哥们问了我一些他们公司的代码的问题,他是得到了别的公司给医院提供的dll,然后调用dll的接口为医院继续写代码..问题是.我也不会啊! 所以趁此机会,好好搞一搞lib和dll.争取能弄明白windows下的lib和dll的一些问题. 一点一点来吧..
什么是lib,什么是dll.为什么要生成lib和dll
不管是静态库还是动态库,两者都是为了共享程序代码,类比的例子就是你封装了一段代码成为一个函数,别的函数能调用你封装的函数,而不必拷贝粘贴一份.这就叫共享程序代码
库通俗的说就是把一些常用函数的目标文件打包在一起并提供相应函数的接口供程序员调用.而程序员只需要知道接口是如何定义的即可.
注意不管是动态库还是静态库你在调用的时候头文件都不是必须的..但是要有一个类似头文件的东西让你知道库里面的函数信息,返回值 函数名 参数 等.如果不提供头文件那么就必须提供一个库的函数说明文档,或者有工具能帮助你看到库里面的函数信息.只有这也你才能在你的代码中调用这些函数啊.. 也就是说有的时候别人只给你一个.so或者.a或者.dll或者.lib你就可以相应的开展你的工作了..
我们知道从你写完程序到生成可执行文件的中间中在vs下面是执行了F7命令,在linux下是执行了makefile,或者自己写了一个g++/gcc xxx -o yyy 那么这个过程包括: C源程序头文件-->预编译处理(cpp)-->编译程序本身-->优化程序-->汇编程序-->链接程序-->可执行文件 1.编译预处理 :预编译程序所完成的基本是对源程序的替代工作.经过这种替代,生成一个没有宏定义.没有条件编译指令,没有特殊符号的输出文件. (a.)宏定义指令 : #define number int -->注意无分号 #undef number--->取消定义的int的替换 (b.)条件编译指令 : #ifdef, #ifndef,#else,#elif,#endif--->通过定义不同的宏来决定编译程序对哪些代码进行处理.预编译程序将根据有关的文件,将那些不必要的代码过滤掉 (c.)头文件包含指令 : #include <>-->库的头文件在 /usr/include目录下 (d.)特殊字符 : 预编译程序可以识别一些特殊的符号.例如源程序中的LINE标识将被解释为当前行号.FILE则被解释为当前编译的c源程序的名称 2.编译 在此阶段预编译程序所要做的工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码或汇编代码 3.优化 优化处理在编译系统中比较艰深的技术.它涉及两方面的问题:编译技术本身(软件方面的优化) \ 机器硬件环境(与硬件相关的优化) 软件方面的优化: 删除公共表达式,循环优化(代码外提,强度削弱,变换循环控制条件,已知量的合并),复写传播,无用赋值的删除 硬件相关的优化:如何充分利用机器的各个硬件寄存器存放的各个变量达到减少对于内存的访问次数.根据机器硬件指向指令的特点(如流水线,risc,cisc,vliw)对 指令进行一些调整使得目标代码比较短,执行的效率比较高 经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器指令,方可能被机器执行 4.汇编 汇编过程时间上就是把汇编语言代码翻译成目标机器指令的过程.机器指令文件即机器语言代码又叫目标文件.一般而言目标文件由段组成.通常目标文件上至少有两个段: 代码段: 该段中所包含的主要是程序的指令.该段一般是可读和可执行的,但一般却不可写 数据段: 主要存放程序中要用到的各种全局变量或静态数据.一般数据是可读 可写 可执行的. unix环境下主要有三种类型的目标文件: a.可重定位文件 :其中包含有用于给其它目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据 b.共享的目标文件 :这种文件存放了适合于在两种上下文里链接的代码和数据:第一种是链接程序可把它与其它可重定位文件以及共享文件一起处理来创建另一个目标文件; 第二种是动态链接程序将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映像 c.可执行文件 :它包含了一个可以被os创建一个进程来执行的文件.汇编程序生成的实际上是第一种类型(可重定位文件)的目标文件.对于后两种还需要其他的一些处理方能得到,这个就是链接程序的工作了 5.链接 由汇编程序生成的目标文件并不能立即就被执行,其中可能还有很多没解决的问题:例如a.cpp里面的一个函数引用了b.cpp里面定义的符号(如变量或者函数); 又例如在程序中调用了某个库文件的函数.这些问题都需要链接程序进行处理.而处理的方法就是把有关系的目标文件相连接(例如上面的a.cpp的目标文件和b.cpp的目标文件.或者a.cpp的目标文件和库的目标文件).换一个说法就是:将在一个文件中引用的符号同该符号在另外一个文件中的符号的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。 根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种: 1.静态链接 这种链接方式下,函数的代码将从函数所在地的静态链接库中被拷贝到最终的可执行程序中.具体过程是:这样函数的代码程序在将被执行的时候被装入可执行程序的进程(也是函数代码的进程,可执行程序和函数代码在一个进程中)的虚拟地址空间中(即拷到可执行程序中).静态链接库实际上是一个目标文件的集合,其中的每一个文件含有库中的一个或者一组相关函数的代码 2.动态链接 在这种链接方式下函数的代码被放到一个叫做动态链接库的地方或者共享对象的某个目标文件中.此时链接程序所做的工作是 在最终的可执行程序中记录下共享对象的名字以及其它的少量而必须的登记信息.在这个可执行文件被执行的时候,动态链接库的全部内容将被映射到运行时相应进程的虚拟地址空间.动态链接库将根据可执行程序中记录的信息找到相应的函数代码. 对于可执行文件中的函数调用,采用动态链接和静态链接的方法都是可以的.使用动态链接可以使得最终的可执行文件短小一些而且如果共享对象被多个进程使用的时候能节约一些内存(在内存中只需要保存一份此共享对象的代码),因为函数代码并没有放入到可执行文件中.而是映射到一个虚拟地址空间中,可执行文件根据它保存的关于函数代码的线索去虚拟地址中访问函数代码.但是这并不是说动态链接就比静态链接要好,因为在有些情况下用静态链接的方式性能会更高一些 6.可执行文件. 文章学习来源http://blog.csdn.net/zhongguoren666/article/details/6672988 |
lib /.a 就是静态库, 在链接的时候被完整的拷贝到可执行文件中,被多次使用就有多份冗余拷贝
dll /.so 就是动态库, 链接时候不复制,程序运行的时候由系统动态加载到内存,供程序调用.系统只加载一次,因此内存里面只有一份代码,然后这份代码被多个使用到它的程序公用
动态库 |
静态库 | |
在程序编译时候不会被链接到目标代码中,而是在程序运行时候才被载入,在程序运行时候还需要动态库 |
在程序编译时候会被链接到目标代码中, 程序运行时候不再需要静态库 |
下一个篇幅学习一下如何在linux下生成静态库和动态库