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

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函数
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 开头 在MacOS和iOS上,可执行程序的启动依赖于xnu内核进程运作和动态链接加载器dyld。其中后者的执行时长...
    RemisKrlet阅读 4,223评论 2 6
  • 一、程序加载 正向开发中,我们平时编写的程序的入口函数都是main.m里面的main函数,所以很多时候都会以为程序...
    KinKen阅读 4,702评论 1 18
  • 应用启动时间,直接影响用户对一款应用的判断和使用体验。头条主app本身就包含非常多并且复杂度高的业务模块(如新闻、...
    hgl阅读 448评论 0 0
  • 探究App的启动过程,有助于我们优化App的启动时间,从main函数之前和main函数之后两个阶段进行分析一下。 ...
    沉江小鱼阅读 1,515评论 1 6
  • main 函数是 iOS 程序的入口,我们写的代码都是在 main 函数之后执行的,但是在夜深人静的时候,我的脑海...
    cosWriter阅读 583评论 0 0