1.mach-o 是一种文件格式,也可以说是可执行 ,目标文件,静态库,动态库dyld
2.dyld就是一个动态的链接器
3.链接 -- 静态链接 -- 和动态链接
4.静态库本质是一群.o文件的集合
5.动态库本质是一个已经链接完全的镜像image,image可以用来 表现任意类型的可执行文件
6.app启动的时候首先是调用exec这个文件的 --> app对应的可执行文件加载进内存 --> dyld加载到内存 --> dyld进行动态链接
7.dyld就是先会加载动态库-->rebase bingding -- >调起main函数,加载动态库就会进行一个 动态库和可执行文件的初始化,然后调用libsystem-->libdispatch-->libobjc-->_dylb_objc_notify_register(&map_images,load_images,unmap_image). 在这里为什么load方法在mian函数之前运行就是因为这个传递过去的load_images方法。load_images就是一个镜像文件,我们corefoundation框架就可以看成,runtime也可以成。map_images 和load_images是关于类的加载用到的。
8.dyld加载的流程图
![](https://img.haomeiwen.com/i9297435/a0cace9c90baa317.jpeg)
![](https://img.haomeiwen.com/i9297435/1b45951dc12e33fe.jpeg)
总结:
在启动App时,真正的加载过程是从exec()函数开始,系统会调⽤exec()函数创建进程,并且分配
内存。然后会执⾏以下的操作
- 把App对应的可执⾏⽂件加载到内存。
- 把dyld加载到内存。dyld也是⼀个可执⾏的程序
- dyld进⾏动态链接。
dyld的具体⼯作内容 - dyld会找到可执⾏⽂件的依赖动态库。接着dyld会将所依赖的动态库加载到内存中。这是⼀个
递归的过程,依赖的动态库可能还会依赖别的动态库,所以dyld会递归每个动态库,直⾄所有
的依赖库都被加载完毕。 - Rebase和Bind。rebase修复的是指向当前镜像内部的资源指针;⽽bind指向的是镜像外部的
资源指针 - 调起main函数,也就是我们程序的⼊⼝,然后我们的程序就开始执⾏了。
dyld进⾏初始化的流程
dyld是⽤来加载可执⾏⽂件所依赖的动态库的。然后会对可执⾏⽂件和可执⾏⽂件所依赖的动态库
进⾏初始化的操作。
在进⾏初始化的操作的时候⾸先会初始化libsystem,否则就会报错。因为在进⾏libsystem初始化
的时候,会初始化libdispatch,在进⾏libdispatch初始化的时候,会初始化libobjc,其他的库,可
能需要依赖runtime基础或者线程相关的基础。所以libsystem的初始化必须放在第⼀位。
在libobjc进⾏初始化的时候,会调⽤⼀个_dyld_objc_notify_register函数,这个函数会给dyld传递
三个回调函数。 - map_images: dyld将image镜像⽂件加载进内存时,会触发该函数
- load_images: dyld初始化image会触发该函数
- unmap_image: dyld将image移除时会触发该函数
然后,dyld会调⽤ map_images 和 load_images 来对image进⾏初始化的操作。
网友评论