返回

iOS 底层探索篇 —— dyld 加载流程(下)

IOS

dyld 加载流程:深入探索 Objective-C 运行时初始化

加载 Mach-O 文件:dyld 加载流程的上半部分

在上一篇文章中,我们研究了 dyld 加载流程的上半部分,了解了 dyld 如何将 Mach-O 可执行文件加载到虚拟内存中。今天,我们将深入了解加载流程的剩余部分,重点关注 Objective-C 运行时初始化。

Objective-C 运行时初始化

加载 Mach-O 文件后,dyld 就会初始化 Objective-C 运行时。该过程主要由 _objc_init 函数完成。在 iOS 系统中,_objc_init 通常从 main() 函数在应用程序启动时调用。

_objc_init 函数执行以下关键步骤:

  • 调用 _dyld_objc_notify_register

此函数注册一个回调函数,以便在 dyld 加载新的 Objective-C 类时调用该函数。它确保 Objective-C 运行时可以跟踪并初始化新加载的类。

  • 调用 _objc_load_image

此函数加载包含 Objective-C 类定义的 Mach-O 文件。它解析类信息,创建类对象,并将其添加到 Objective-C 运行时的类表中。

  • 调用 _objc_init_classes

此函数初始化 Objective-C 类。它调用类构造函数,执行类变量的初始化,并设置类方法的实现。

深入剖析 _dyld_objc_notify_register

_dyld_objc_notify_register 函数是一个回调函数,在 dyld 加载新的 Objective-C 类时调用。它接收指向 map_images 结构体的指针,该结构体包含有关新加载的 Mach-O 文件的信息。

该函数执行以下步骤:

  • 获取 Mach-O 文件的 Objective-C 部分。
  • 解析 Objective-C 类信息。
  • 创建类对象并将其添加到 Objective-C 运行时的类表中。
  • 调用 _objc_register_classes,该函数通知 Objective-C 运行时关于新加载的类。

代码示例

void _dyld_objc_notify_register(struct mach_header *mh, intptr_t vm_slide) {
  // ...
}

总结

dyld 加载流程对于 iOS 系统中的应用程序启动至关重要,因为它加载 Mach-O 可执行文件并初始化 Objective-C 运行时。通过了解 _dyld_objc_notify_register_objc_load_image 等函数的底层实现,我们可以深入理解 dyld 在 iOS 系统启动过程中的作用。

常见问题解答

  • dyld 加载流程何时发生?
    它在应用程序启动时发生,通常从 main() 函数调用 _objc_init 函数。

  • Objective-C 运行时是如何初始化的?
    Objective-C 运行时由 _objc_init 函数初始化,该函数调用 _dyld_objc_notify_register_objc_load_image_objc_init_classes 函数。

  • _dyld_objc_notify_register 函数的作用是什么?
    它注册一个回调函数,以便在加载新的 Objective-C 类时调用该函数,从而确保 Objective-C 运行时可以跟踪并初始化这些类。

  • _objc_load_image 函数的作用是什么?
    它加载包含 Objective-C 类定义的 Mach-O 文件,并解析类信息、创建类对象并将其添加到 Objective-C 运行时的类表中。

  • _objc_init_classes 函数的作用是什么?
    它初始化 Objective-C 类,调用类构造函数,执行类变量的初始化,并设置类方法的实现。