美文网首页
iOS-main函数之前

iOS-main函数之前

作者: doudo | 来源:发表于2017-09-27 15:27 被阅读194次

我们一般知道 App 程序入口从执行main函数开始,但其实在main函数之前程序做了很多工作。

一、内核启动

APP是由内核引导启动的,kernel内核做好所有准备工作后会得到线程入口及main入口,但是线程不会马上进入main入口,因为还要加载动态链接器(dyld),dyld会将入口点保存下来,等dyld加载完所有动态链接库等工作之后,再开始执行main函数。
初始化空间创建进程等,最重要的是载入动态链接器。

二、动态链接器(dyld)

动态链接库是一组源代码的模块,每个模块包含一些可供应用程序或者其他动态链接库调用的函数,在应用程序调用一个动态链接库里面的函数的时候,操作系统会将动态链接库的文件映像映射到进程的地址空间中,这样进程中所有的线程就可以调用动态链接库中的函数了。

1. 加载动态链接库

dyld是苹果的动态链接器,iOS中系统所有的framework都是动态链接的,在执行我们的代码之前dyld需要加载所有动态库。
使用动态库的好处:

  • 代码共用,很多程序都动态链接了这个lib,但它们在内存和磁盘中只有一份。
  • 易于维护,由于这些lib是程序执行的时候才去link,所以这些lib很容易去做更新。
  • 减少体积,不用像静态库那样被打包进执行文件,可执行文件体积能减少很多。

2. 共享缓存

当构建一个应用程序时,将会链接各种各样的库,它们又会依赖于其他的动态库,需要加载的动态库将会非常多,为了缩短时间动态链接器使用的共享缓存。操作系统中有个单独的文件,这个文件中包含了绝大多数的动态库,这些动态库都已经链接成了一个文件,并且处理好了它们之间的符号关系。当加载一个可执行文件或库时,动态链接器首先会检查共享缓存中是否存在,如果存在,直接拿出来使用。

3. 加载类、方法等符号

简单的说是ImageLoader和dyld、runtime配合将类加载进内存。这里Image我们理解为二进制文件。
整个过程:

  1. dyld将可执行文件初始化
  2. 交由ImageLoader加载Image二进制文件(包含了类、方法等各种符号)
  3. 当新 image 加载进来后交由 runtime 大厨去解析这个二进制文件的符号表和代码
  4. runtime 接手后调用 map_images做解析和处理,接下来 load_images 中调用 call_load_methods 方法,遍历所有加载进来的 Class,按继承层级依次调用 Class 的 +load 方法和其 Category 的 +load 方法。
    至此,可执行文件和动态库中的所有符号(Class、Selector...)都已经成功加载进内存,被runtime所管理,在这之后,runtime的那些方法都可以使用了(动态添加class、方法混合等)。

4. 扩展+load

可以知道,所有 Class 的 load 方法都是在 main 函数之前被调用的,且只会被调用一次。注意,这里调用 load 方法是直接使用函数内存地址 (*load_method)(cls,SEL_load) ,而不是使用消息发送 objc_msgSend 的方式,所以子类中不能调用父类的load方法。

三、main函数

所有初始化工作结束后,终于来到了main函数:

  1. 执行UIApplicationMain函数
  2. 创建Application对象,创建ApplicationDelegate,并设为Application的代理。
  3. 创建RunLoop主循环,代理开始监听事件
  4. 启动完毕后会执行didFinishLaunching,创建keyWindow,以及weindow的跟视图控制器。
  5. 显示窗口。

资料:
iOS 程序 main 函数之前发生了什么
iOS:App启动流程

相关文章

  • iOS-main函数之前

    我们一般知道 App 程序入口从执行main函数开始,但其实在main函数之前程序做了很多工作。 一、内核启动 A...

  • ios-main使用

    跳转 在view中选中 isIntial View Controlle 代码跳转单指双击页面缩放 第一个页面 连接...

  • 2-8

    不要学我把函数写在主函数之前。。。

  • 启动优化

    项目APP的启动优化分为两个阶段:main()函数之前 、main()函数之后 1、main()函数之前优化:...

  • iOS Main 函数之前探究

    操作系统是应用程序和硬件之间的中间人,硬件中最主要的是CPU,处理应用事件。 有操作系统知道 CPU 正在处理哪个...

  • Main函数之前的Load

    整个运行时初始化时 _objc_init 注册的回调 dyld_register_image_state_chan...

  • [Assembly about]main函数之前

    记一篇好的文章:http://blog.chinaunix.net/uid-24774106-id-3318673...

  • js函数和原型对象

    函数提升(Hoisting):函数可以在声明之前调用 自调用函数、函数声明、函数表达式、匿名函数、箭头函数: 自调...

  • iOS加快app启动速度——动态库转静态库方法

    app启动速度分mian()函数之前和main()函数之后,其中main()函数之前的流程大概有以下几个:dyld...

  • php面试:函数

    有条件函数和无条件函数: 无条件函数可以在定义之前调用,有条件函数调用之前必须定义(否则会报未定义)。 1.函数名...

网友评论

      本文标题:iOS-main函数之前

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