美文网首页iOS底层原理
iOS底层原理 12 : 应用程序的加载

iOS底层原理 12 : 应用程序的加载

作者: smooth_lgh | 来源:发表于2020-09-27 16:55 被阅读0次

    一、应用程序的加载

    APP加载过程:程序启动依次加载dyldlibSystemlibdispathc.dyldlibobjc动态库,最终调用_objc_init()方法,在此方法中Runtime向dyld注册回调函数,加载新的image,执行map_imagesload_imagesimageLoader加载image,调用main函数

    二、dyld动态链接器

    dyld(the dynamic link editor)是苹果的动态链接器,是苹果操作系统一个重要组成部分,在系统内核做好程序准备工作之后,交由dyld负责余下的工作。

    1.dyld的加载过程:
    1.环境变量的配置
    2.共享缓存 checkSharedRegionDisable()
    3.主程序的初始化
    4.加入动态库 loadInsertedDylib()
    5.link主程序 link(sMainExecutable, sEnv.DYLD_BIND_AT_LAUNCH, true, ImageLoader::RPathChain(NULL, NULL), -1)
    6.link动态库 link(image, sEnv.DYLD_BIND_AT_LAUNCH, true, ImageLoader::RPathChain(NULL, NULL), -1)
    7.initializeMainExecutable运行所有初始化程序
    8.main notifyMonitoringDyldMain()

    2.reloadAllImages加载镜像文件的步骤:

    • 实例化主程序instantiateFromLoadedImage(),内核会映射到主要可执行文件中,我们需要为映射到主可执行文件的文件,创建ImageLoader。在此方法中,然后读取image,然后addImage()读取加载镜像文件。会先在instantiateMainExecutable()中,会确认此mach-o文件中是否具有压缩的LINKEDIT以及段数。
    • 加载插入任何动态库loadInsertedDylib(*lib),将其读取为镜像文件iamge。
    • 链接库。先遍历,读取image,然后link。在link中,递归插入动态加载的镜像文件。

    3.initializeMainExecutable()运行所有初始化程序步骤:

    • runInitializers()
    • processInitializers初始化准备。
    • processInitializers中,遍历iamge.count,递归一个个开始初始化条件images[i]->recursiveInitialization
    • 在递归开始初始化条件中recursiveInitialization,通过notifySingle方法,对单个镜像通知开始初始化。获取镜像文件的真实地址(*sNotifyObjCInit)(image->getRealPath(), image->machHeader()), 而notifySingle中的sNotifyObjCInit是在objc_init()中注册传递过来的,所以只有当objc_init()调用时,重新加载image
    • notifySingle方法之后,遍历初始化this->doInitialization(context)
    • 在doInitialization方法中,先调用doImageInit(context),确保libSystem库必须提前初始化完成。再调用doModInitFunctions()方法,对 C++和构造函数处理,然后调用libSystem_initializer方法,调用libdispatch_init,调用_os_object_init,最终调用_objc_init方法。
    • _objc_init方法来注册回调函数,重新加载images,执行map_imagesload_imagesimageLoader加载image,调用main函数。

    面试题

    1.main()之前系统做了哪些工作?

    1)dyld 开始将程序二进制文件初始化

    2)交由ImageLoader读取 image,其中包含了我们的类,方法等各种符号(Class、Protocol 、Selector、 IMP)

    3)由于runtimedyld 绑定了回调,当image加载到内存后,dyld会通知runtime进行处理

    4)runtime 接手后调用map_images做解析和处理

    5)接下来load_images中调用call_load_methods方法,遍历所有加载进来的Class,按继承层次依次调用Class+load和其他Category+load方法

    6)至此 所有的信息都被加载到内存中

    7)最后dyld发送调main函数的通知,接下来就是main函数

    相关文章

      网友评论

        本文标题:iOS底层原理 12 : 应用程序的加载

        本文链接:https://www.haomeiwen.com/subject/xhjluktx.html