美文网首页
iOS系统架构基础概念

iOS系统架构基础概念

作者: 生产八哥 | 来源:发表于2021-02-05 19:00 被阅读0次

    iOS 系统架构

    iOS 系统是基于 ARM 架构的,大致可以分为四层:

    • 最上层是用户体验层,主要是提供用户界面。这一层包含了 SpringBoard、Spotlight、Accessibility。
    • 第二层是应用框架层,是开发者会用到的。这一层包含了开发框架 Cocoa Touch。
    • 第三层是核心框架层,是系统核心功能的框架层。这一层包含了各种图形和媒体核心框架、Metal 等。
    • 第四层是 Darwin 层,是操作系统的核心,属于操作系统的内核态。这一层包含了系统内核 XNU、驱动等。

    Darwin 的内核是 XNU,而 XNU 是在 UNIX 的基础上做了很多改进以及创新。


    XNU

    XNU 内部由 Mach、BSD、驱动 API IOKit 组成,这些都依赖于 libkern、libsa、Platform Expert。

    Mach微内核

    Mach是作为 UNIX 内核的替代,主要解决 UNIX 一切皆文件导致抽象机制不足的问题,为现代操作系统做了进一步的抽象工作。 Mach 负责操作系统最基本的工作,包括进程和线程抽象、处理器调度、进程间通信、消息机制、虚拟内存管理、内存保护等。

    进程对应到 Mach 是 Mach Task,Mach Task 可以看做是线程执行环境的抽象,包含虚拟地址空间、IPC 空间、处理器资源、调度控制、线程容器。

    Mach 的模块包括进程和线程都是对象,对象之间不能直接调用,只能通过 mach_msg() 函数进行通信。你可以通过 mach_msg_trap() 函数触发陷阱,从而切至 Mach,由 Mach 里的 mach_msg() 函数完成实际通信。

    BSD宏内核

    • Mach 是微内核,可以将操作系统的核心独立在进程上运行,不过,内核层和用户态各层之间切换上下文和进程间消息传递都会降低性能。为了提高性能,苹果深度定制了BSD宏内核,使其和 Mach 混合使用。

    • 宏内核 BSD 是对 Mach 封装。

    • 随着 iPhone 硬件升级,为了更好地利用多核,BSD 加入了工作队列,以支持多核多线程处理,这也是 GCD 能更高效工作的基础

    IOKit

    除了微内核 Mach 和宏内核 BSD 外,XNU 还有 IOKit。IOKit 是硬件驱动程序的运行环境,包含电源、内存、CPU 等信息。IOKit 底层 libkern 使用 C++ 子集 Embedded C++ 编写了驱动程序基类,比如 OSObject、OSArray、OSString 等,新驱动可以继承这些基类来写。


    XNU加载App

    iOS 的可执行文件和动态库都是 Mach-O 格式,所以加载 APP 实际上就是加载 Mach-O文件。

    Mach-O

    一个完成的Mach-O文件主要分为三大部分:

    • Header Mach-O头部:主要是Mach-O的cpu架构,文件类型以及加载命令等信息

    • Load Commands 加载命令:描述了文件中数据的具体组织结构,不同的数据类型使用不同的加载命令表示

    • Data 数据:数据中的每个段(segment)的数据都保存在这里,段的概念与ELF文件中段的概念类似。每个段都有一个或多个部分,它们放置了具体的数据与代码,主要包含代码,数据,例如符号表,动态符号表等等。主要集中体现在TEXTDATA两段里。

    加载

    加载 Mach-O 文件的是 exec_mach_imgact() 函数。exec_mach_imgact() 会通过 load_machfile() 函数加载 Mach-O 文件,根据解析 Mach-O 后得到的 load command 信息,通过映射方式加载到内存中。还会使用 activate_exec_state() 函数处理解析加载 Mach-O 后的结构信息,设置执行 App 的入口点。

    设置完入口点后会通过 load_dylinker() 函数来解析加载 dyld,然后将入口点地址改成 dyld 的入口地址。这一步完后,内核部分就完成了 Mach-O 文件的加载。剩下的就是用户态层 dyld 加载 App 了。

    Dyld 的入口函数是 __dyld_start,dyld 属于用户态进程,不在 XNU 里。__dyld_start 会加载 App 相关的动态库,处理完成后会返回 App 的入口地址,然后到 App 的 main 函数。

    流程可以概括为:

    1. fork 新进程;fork 之前内存并没有分配给新进程,是在 fork 新进程后再分配的,调用的函数是 exec_activate_image,这个函数会依据 execsw 加载二进制文件格式进行内存映射,对内存进行分配。
    2. 为 Mach-O 分配内存;
    3. 解析 Mach-O;
    4. 读取 Mach-O 头信息;
    5. 遍历 load command 信息,将 Mach-O 映射到内存;
    6. 启动 dyld。

    相关文章

      网友评论

          本文标题:iOS系统架构基础概念

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