美文网首页iOS底层收集
OC底层原理探索-07应用程序加载

OC底层原理探索-07应用程序加载

作者: ricefun | 来源:发表于2020-02-17 20:01 被阅读0次

    app加载分析

    我们知道app加载其实是依赖许多的底层库的,库是可执行的代码的而二进制文件,当加载的时候就会被操作系统写入到内存中。库分为静态库(.a、.lib)动态库(framework)

    静态库和动态库区别

    首先我们看一下编译过程图


    编译过程 而动静态库的区别在于他们被编译的顺序 静动态库编译顺序 静态库会被多次编译,而动态库可以做到按需编译,所以动态库可以减少程序在打包后app的体积(占用的内存大小),共享了内存,节约内存资源(eg:UIKit、CoreFoundation、libObjc...)
    app启动
    app启动过程图

    上图中image是镜像文件

    dyld加载过程

      1. _dyld_start 连接开始
      1. uInptr_start(...)应用程序进来 dyld::_main
      • 2.1 环境变量相关处理
      • 2.2 加载共享缓存
      • 2.3 将dlyd本身添加到UUID列表
      • 2.4 reloadAllImages
        • 2.4.1实例化主程序
        • 2.4.2加载任何插入动态库
        • 2.4.3连接库
      • 2.5 运行所有初始化程序
      • 2.6 通知监听dlyd的main

    void _objc_init(void)

    void _objc_init(void)
    {
        static bool initialized = false;
        if (initialized) return;
        initialized = true;
        
        // fixme defer initialization until an objc-using image is found?
        environ_init();
        tls_init();
        static_init();
        lock_init();
        exception_init();
        // 保存 - libobjc - dyld
        // C++ 怎么去做到通知
        // 指针 - 回调 - 函数的地址
        
        // 这里就是我们的数据 - images  - objc lib
        // dyld
        _dyld_objc_notify_register(&map_images, load_images, unmap_image);
    }
    
    截屏2020-02-1812.09.54.png
    环境变量enviro_init();
    void environ_init(void) 
    {
        if (issetugid()) {
            // All environment variables are silently ignored when setuid or setgid
            // This includes OBJC_HELP and OBJC_PRINT_OPTIONS themselves.
            return;
        } 
       ...
       ...
    
            for (size_t i = 0; i < sizeof(Settings)/sizeof(Settings[0]); i++) {
                const option_t *opt = &Settings[i];            
               // if (PrintHelp) _objc_inform("%s: %s", opt->env, opt->help);
               //去掉if (PrintHelp)打印判断,可以看到好多环境变量
                _objc_inform("%s: %s", opt->env, opt->help);
                if (PrintOptions && *opt->var) _objc_inform("%s is set", opt->env);
            }
        }
    }
    

    注销上面标注的代码进行打印,可以看到lldb中的具体内容;如下


    环境变量命遍历打印 这里的environ_init()函数负责环境的初始化,里面可以打印我们日常需要的调试数据,eg:OBJC_PRINT_LOAD_METHODS;那么如何使用呢?打开editScheme - 在debug模式下选择Arguments - 点击+号添加:OBJC_PRINT_LOAD_METHODS选择YES:如下图
    然后重新跑一遍程序,查看打印。你可以看到所有load的方法

    map_Images&Load_Images

    将在下一章详细探究map_Images&Load_Images

    截屏2020-02-1720.04.01.png
    map_Images
    Load_Images

    总结

    APP启动过程

    • APP启动
    • 加载libSystem
    • Runtime向dyld注册回调函数
    • 加载新的image
    • 执行map_images、load_images
    • 调用main函数

    相关文章

      网友评论

        本文标题:OC底层原理探索-07应用程序加载

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