本文源自本人的学习记录整理与理解,其中参考阅读了部分优秀的博客和书籍,尽量以通俗简单的语句转述。引用到的地方如有遗漏或未能一一列举原文出处还望见谅与指出,另文章内容如有不妥之处还望指教,万分感谢!
什么是库 ?
库就是程序代码的集合,将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和插件之间共享动态库还是可行的。
iOS系统专属的framework是共享的(如 UIKit),但是而我们自己使用Cocoa Touch Framework 制作的动态库是放到app bundle中,运行在沙盒中的。
静态库和动态库的存在的形式
静态库:以 .a 和 .framework 为文件后缀名。
动态库:以.tbd(之前叫.dylib)和framework为文件后缀名。(系统直接提供给我们的framework都是动态库)
理解: .a是一个纯二进制文件,.framework中出了有二进制文件之外还有资源文件。.a 要有.h文件以及资源文件配合使用;.framework文件可以直接使用。总得来说,.a + .h +sourceFlie = .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() { } .m文件实现
最后,链接器会用函数的实际地址来代替函数引用。
动态库的处理方式
首先,对于动态库而言其实分:动态链接库和动态加载库两种,这两种最本质的区别还是加载时机。
动态链接库: 在没有被加载到内存的前提下,当可执行文件被加载,动态库也随着被加载到内存中。在linked framework and Libraries 设置的一些share libraries 【随着程序启动而启动】
动态加载库:当需要的时候再使用 dlopen 等通过代码或者命令的方式来加载。【在程序启动之后】
但是不论是那种动态库,相比较于静态库,动态库处理起来要棘手的多。由于动态库是动态的,所以你事先不知道某个函数的具体地址。因此动态连接器在链接函数的时候需要做大量的工作。
因为动态库在链接函数需要做大量的工作,而静态库已经事先处理好了。所以单纯的再所有都没有加载的情况下,静态库的加载速度会更快一点。虽然动态库更加耗时,但是对于加载过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 来进行动态更新!
重要参考文档(一定要看):
谈谈 Mach-O
Mach-O
在制作 framework 的时候需要选择这个 Mach-O Type.
为Mach Object文件格式的缩写,它是一种用于可执行文件,目标代码,动态库,内核转储的文件格式。作为a.out格式的替代,Mach-O提供了更强的扩展性,并提升了符号表中信息的访问速度。
参考链接: https://www.cnblogs.com/junhuawang/p/7598236.html