什么是库 ?
库就是程序代码的集合,将N个文件组织起来,是共享程序代码的一种方式。库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。
库的分类
- 开源库:源代码是公开的,可以看到每个实现文件(.m文件)的实现,例如GitHub上的常用的开源库:AFNetworking、SDWebImage等;
- 闭源库:不公开源代码,是经过编译后的二进制文件,看不到具体的实现。闭源库又分为:静态库 和 动态库
1、linux中静态库和动态库区别:库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。静态库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。动态库:这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
2、iOS开发中静态库和动态库区别:静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
静态库好处:
- 模块化,分工合作,提高了代码的复用及核心技术的保密程度
- 避免少量改动经常导致大量的重复编译连接
- 也可以重用,注意不是共享使用
动态库 好处:
- 使用动态库,可以将最终可执行文件体积缩小,将整个应用程序分模块,团队合作,进行分工,影响比较小
- 使用动态库,多个应用程序共享内存中得同一份库文件,节省资源
- 使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。
- 应用插件化
- 软件版本实时模块升级
- 在其它大部分平台上,动态库都可以用于不同应用间共享, 共享可执行文件,这就大大节省了内存。iOS平台 在 iOS8 之前,苹果不允许第三方框架使用动态方式加载,从 iOS8 开始允许开发者有条件地创建和使用动态框架,这种框架叫做 Cocoa Touch Framework。虽然同样是动态框架,但是和系统 framework 不同,app 中使用 Cocoa Touch Framework?制作的动态库 在打包和提交 app 时会被放到 app ?main bundle 的根目录?中,运行在沙盒里,而不是系统中。也就是说,不同的 app 就算使用了同样的 framework,但还是会有多份的框架被分别签名,打包和加载。不过 iOS8 上开放了?App Extension?功能,可以为一个应用创建插件,这样主app和插件之间共享动态库还是可行的。苹果系统专属的framework 是共享的(如UIKit), 但是我们自己使用 Cocoa Touch Framework?制作的动态库是放到?app bundle 中,运行在沙盒中的
静态库和动态库的存在的形式
- 静态库:以.a 和 .framework为文件后缀名。
- 动态库:以.tbd(之前叫.dylib) 和 .framework 为文件后缀名。(系统直接提供给我们的framework都是动态库!)理解:.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。.a,要有.h文件以及资源文件配合,.framework文件可以直接使用。总的来说,.a + .h + sourceFile = .framework。所以创建静态库最好还是用.framework的形式
静态库和动态库的区别
不同点:
- 静态库在链接时,会被完整的复制到可执行文件中,如果多个App都使用了同一个静态库,那么每个App都会拷贝一份,缺点是浪费内存。类似于定义一个基本变量,使用该基本变量是是新复制了一份数据,而不是原来定义的;
- 动态库不会复制,只有一份,程序运行时动态加载到内存中,系统只会加载一次,多个程序共用一份,节约了内存。类似于使用变量的内存地址一样,使用的是同一个变量;共同点:
- 静态库和动态库都是闭源库,只能拿来满足某个功能的使用,不会暴露内部具体的代码信息
静态库的处理方式
- 对于一个静态库而言,其实已经是编译好的了,类似一个 .o?的集合 这里并没有连接。在 build 的过程中只会参与链接的过程,而这个链接的过程简单的讲就是合并,并且链接器只会将静态库中被使用的部分合并到可执行文件中去。相比较于动态库,静态库的处理起来要简单的多,具体如下图:
- 链接器会将所有**.o**用到的 global symbol?和?unresolved symbol?放入一个临时表,而且是?global symbol?是不能重复的。
- 对于静态库的 .o?, 连接器会将没有任何?symbol?在?unresolved symbol table?的给忽略。
- unresolved symbol?类似?extern int test();?--- **.h **的 声明?
- global symbol?类似?void test() { print("test")}?--??.m?的 实现?
动态库的处理方式
- 首先,对于动态库而言其实分 动态链接库?和?动态加载库?两种的,这两个最本质的区别还是加载时间。
-
- 动态链接库:在没有被加载到内存的前提下,当可执行文件被加载,动态库也随着被加载到内存中。在 Linked Framework and Libraries 设置的一些 share libraries。【随着程序启动而启动】
- 动态加载库:当需要的时候再使用 dlopen 等通过代码或者命令的方式来加载。【在程序启动之后】
- 但是不论是哪种动态库,相比较与静态库,动态库处理起来要棘手的多。由于动态库是动态的,所以你事先不知道某个函数的具体地址。因此动态链接器在链接函数的时候需要做大量的工作。
因为动态库在链接函数需要做大量的工作,而静态库已经实现处理好了。所以单纯的在所有都没有加载的情况下,静态库的加载速度会更快一点。而在?iOS 开发中的『库』(一)?提到的有所不妥,正确应该是,虽然动态库更加耗时,但是对于在加载过的share libraries不需要再加载的这个前提下,使用动态库可以节省一些启动时间。
- 而实现这个动态链接是使用了 Procedure Linkage Table (PLT)。首先这个?PLT?列出了程序中每一个函数的调用,当程序开始运行,如果动态库被加载到内存中,PLT?会去寻找动态的地址并记录下来,如果每个函数都被调用过的话,下一次调用就可以通过?PLT?直接跳转了,但是和静态库还是有点区别的是,每一个函数的调用还是需要通过一张?PLT。这也正是 sunny 所说的所有静态链接做的事情都搬到运行时来做了,会导致更慢?的原因。
从源代码到app
当我们点击了 build 之后,做了什么事情呢?
- 预处理(Pre-process):把宏替换,删除注释,展开头文件,产生 .i 文件。
- 编译(Compliling):把之前的 .i 文件转换成汇编语言,产生 .s文件。
- 汇编(Asembly):把汇编语言文件转换为机器码文件,产生 .o 文件。
- 链接(Link):对.o文件中的对于其他的库的引用的地方进行引用,生成最后的可执行文件(同时也包括多个 .o 文件进行 link)。
相关动态库和静态库的创建
动态库动态更新问题
能否动态库的方式来动态更新AppStore上的版本呢?
framework本来是苹果专属的内部提供的动态库文件格式,但是自从2014年WWDC之后,开发者也可以自定义创建framework实现动态更新(绕过apple store审核,从服务器发布更新版本)的功能,这与苹果限定的上架的app必须经过apple store的审核制度是冲突的,所以含有自定义的framework的app是无法在商店上架的,但是如果开发的是企业内部应用,就可以考虑尝试使用动态更新技术来将多个独立的app或者功能模块集成在一个app上面!(我开发的就是企业内部使用的app,我们将企业官网中的板块开发成4个独立的app,然后将其改造为framework文件最终集成在一款平台级的app当中进行使用,这样就可以在一款app上面使用原本4个app的全部功能!)
使用自定义的动态库的方式来动态更新只能用在?in house(企业发布) 和develop?模式却但不能在使用到?AppStore?因为在上传打包的时候,苹果会对我们的代码进行一次 Code Singing,包括 app 可执行文件和所有Embedded 的动态库。因此,只要你修改了某个动态库的代码,并重新签名,那么 MD5 的哈希值就会不一样,在加载动态库的时候,苹果会检验这个 hash 值,当苹果监测到这个动态库非法时,就会造成 Crash
iOS 如何使用 framework 来进行动态更新!
重要参考文档(一定要看):
- iOS 利用 Framework 进行动态更新
谈谈 Mach-O
Mach-O
- 在制作 framework 的时候需要选择这个 Mach-O Type.
- 为Mach Object文件格式的缩写,它是一种用于可执行文件,目标代码,动态库,内核转储的文件格式。作为a.out格式的替代,Mach-O提供了更强的扩展性,并提升了符号表中信息的访问速度。
?
|