返回

OC 底层原理 11:类的加载(上)

IOS

前言

在上一篇文章 OC 底层原理 10:dyld 与 objc 的关联 中,我们了解了 dyld 和 objc 是如何关联的。本文的主要目的是理解类的相关信息是如何加载到内存的,其中重点关注 map_image。

类的加载流程

类的加载流程可以大致分为以下几个步骤:

  1. 加载镜像 :dyld 会将可执行文件或动态库中的 Mach-O 文件加载到内存中,形成一个镜像。
  2. 重定位镜像 :将镜像中的符号地址重新计算为加载后的地址,以便程序可以在正确的地址空间运行。
  3. 绑定镜像 :将镜像中的符号与实际的函数或数据地址绑定起来。
  4. 初始化镜像 :调用镜像中指定的初始化函数,完成一些必要的初始化工作。

map_image

map_image 是 dyld 中负责将 Mach-O 文件加载到内存并创建镜像的函数。其原型如下:

int map_image(struct mach_header *header, unsigned long slide,
              vm_prot_t protection, vm_prot_t max_protection,
              vm_offset_t *addr);

其中,参数 header 是指向 Mach-O 文件头部的指针,slide 是滑动链接的偏移量,protection 和 max_protection 指定了映射的内存保护属性,addr 是输出参数,返回映射后的镜像的地址。

map_image 的主要工作流程如下:

  1. 校验 Mach-O 头部 :检查 Mach-O 文件头部的有效性,确保它是有效的 Mach-O 文件。
  2. 分配内存 :为镜像分配所需的内存空间。
  3. 复制数据段 :将 Mach-O 文件中的数据段复制到分配的内存空间中。
  4. 重定位符号 :根据滑动链接偏移量,重定位 Mach-O 文件中的所有符号地址。
  5. 绑定符号 :将镜像中的符号与实际的函数或数据地址绑定起来。
  6. 执行初始化函数 :调用 Mach-O 文件中指定的初始化函数,完成一些必要的初始化工作。
  7. 返回镜像地址 :将映射后的镜像地址返回给调用者。

总结

map_image 是 dyld 中负责将 Mach-O 文件加载到内存并创建镜像的核心函数。它通过校验 Mach-O 头部、分配内存、复制数据段、重定位符号、绑定符号和执行初始化函数等一系列步骤来完成类的加载过程。理解 map_image 的工作原理对于深入了解 OC 运行时至关重要。