iOS 底层探索篇 —— dyld 加载流程(下)
2023-12-07 18:18:32
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 类,调用类构造函数,执行类变量的初始化,并设置类方法的实现。