一、编译原理:
一般编程语言可分为编译型语言和直译型语言,我们常用的Objective-C就属于编译行语言(这边就先忽略直译型语言了)。
OC编译的执行过程大概分为:
1、把源文件(.h .m .cpp),先进行预编译(把一些宏定义进行预处理)操作
2、把OC高级代码编译成汇编底层代码
3、链接.a .lib 等静态库文件,依赖UIKit,写入可执行文件
4、生成可执行文件
由于编译高级语言会生成汇编代码,汇编代码在CPU调度的时候执行速度是最快的,所以执行效率最高。
接下来直接用代码看一下效果:
LGperson *p = [LGperson alloc];
[p instanceMethod];
[LGperson classMethod];
NSLog(@"hello world!");
首先创建一个LGperson的NSObject文件,添加一个实例方法(instanceMethod)和类方法(classMethod),在main.m里添加以上代码,然后进行编译操作。
会出现一个LGTest的可执行文件,打开执行
通过这个可执行文件,可以看出来这样一个加载流程,在程序还没运行,只是在编译的时候,hello world就被打印出来了。
二、库文件
在讲编译和加载的时候,不得不提一个最重要的东西,就是库文件,一般库文件可分为静态库和动态库,总结了一下他们的特点。
静态库:常用.a .lib,在链接阶段会将汇编生成的目标文件(.o)与引用的库一起打包生成可执行文件。
动态库:常用.so .framework .dl等,编译的时候不会用,运行的时候才调用,减少打包app的体积,共享内存,热更新(更新动态库),由于动态库可以进行更新操作,容易被注入恶意代码,就会变得不稳定不安全。常用动态库有UIKit、libsystems、libobjc、CFFoundation框架等。
三、APP启动流程
APP启动的底层原理:
_dyld_objc_notify_register(&map_images, load_images, unmap_image);
1、加载libsystems,通过runtime向dylb(动态链接器)注册回调函数_dyld_objc_notify_register(dyld提供,只能被runtime使用)
2、加载images库文件。
3、执行map_images(处理由dyld映射的库文件)和load_images(加载所有+load方法)
4、调用main函数
系统库通过dyld管理,加入runtime,通过dyld赋予静态库一个运行时的功能。