iOS启动优化之Mach-O相关术语

扫一扫关注公众号,得到更多iOS相关内容前端


这篇文章讲的是OS启动优化相关的理论部分。安全

Mach-O术语

Mach-O是运行时可执行文件的文件类型,这些文件类型包括:app

  • 可执行文件:应用中最重要的二进制文件,也是应用扩展文件的主二进制文件。
  • Dylib:动态连接库(又称DSO或DLL)。动态连接库包括:iOS中用到的全部系统framework,加载OC runtime方法的libobjc,系统级别的libSystem,例如libdispatch(GCD)和libsystem_blocks(Block)。
  • Bundle:捆绑包,不能被连接的Dylib,只能在运行时使用dlopen()加载,macOS的插件会用到它。

Image:指的是任意这三种类型。 Framework:这里指的是一个特殊的Dylib,它有一个目录结构用来存储该Dylib所需的文件。函数

全部动态连接库和静态库.a和全部类文件.o文件最终都由Dyld(apple的动态连接器)加载到内存中。布局

Mach-O镜像文件

Mach-O的镜像文件被分割成一些segment(段),segment名字都是大写的。全部的segments都是page(页)大小的整数倍。优化

页的大小跟硬件有关:加密

  • arm64上是16KB
  • 其他的为4KB

一个Segment包含若干个sections(分区),因此section名字都是小写的,分区不遵循页面大小,分区间是不重叠的。 spa

几乎全部的二进制文件都包含这三个段(segment):__TEXT,__DATA和__LINKEDIT:插件

  • TEXT段是文件的开头,包含了Mach的头文件、被执行的代码和只读常量(如C字符串)。只读可执行(r-x)。
  • DATA段是重写段,包含全部的:全局变量,静态变量等。可读写(rw-)。
  • LINKEDIT段包含加载程序的元数据,好比函数的名称和地址。只读(r-)。

Mach-O的通用文件

假设你生成一个64位的iOS应用,那么你就会有一个Mach-O文件,若是你也想让它在32位的机器上运行,Xcode里会发生什么变化呢? Xcode会从新生成一个Mach-O文件,这个是为32位生成的armv7s,以后Xcode会将这两个文件合并成第三个文件,这个文件就是Mach-O的通用文件。线程

这个文件前端有一个头文件,全部的头文件都有一个全部体系的列表,它们的偏移值也在文件里,该文件占用一页空间大小。

虚拟内存

虚拟内存是一个间接层。每一个进程都是一个逻辑地址空间,映射到RAM(随机存取存储器)的某个物理页, 这种映射不必定是一对一的。

特色以下:

  • 若是有一个逻辑地址不映射任何物理RAM,当进程访问该地址时,就会触发page defult,内核会中止该线程,并试图找出解决方案。

  • 当多个逻辑地址映射到同一物理RAM上时,会形成多进程共享内存。

  • 基于文件的映射

    • 不用一次性将整个文件读入物理RAM,可使用分页映射(mmap()函数)的方式读取。也就是把文件某个段映射到进程逻辑内存的某个页上。
    • lazy reading(懒加载)。

    总结:Dylib或者imgae的TEXT段能够映射到多个进程,将会形成读取迟缓,而全部这些页面能够在进程间共享。

  • Copy-On-Write(写入时复制),简称COW。也就是多个进程共享一页内存空间时,一旦有进程要作写操做,它会将这页内存内容复制一份出来,而后从新映射逻辑地址到新的RAM页上。也就是这个进程本身拥有了那分内存的拷贝。

  • Dirty vs. clean pages:上面复制出来的副本被认为是脏页面,脏页面是指含有进程特定信息的页面。干净页面是指内核能够按照须要从新创建的页面,好比从新读取磁盘。脏页面比干净页面要昂贵的多,

  • Permissions(权限界限):这里指能够标记一个页面,可读,可写或可执行,或者是它们的任意组合。

Mach-O镜像加载

在多个进程加载Mach-O镜像时 __TEXT和__LINKEDIT是只读的,都是能够共享内存的。而__DATA是可读写的,会产生dirty page。当dyld执行结束后,__LINKEDIT就没用了,对应的内存页就会被回收。

安全

两点安全问题会影响Dyld:

  • ASLR:地址空间布局随机化。镜像会在随机的地址上加载。
  • 代码签名:为了在运行时验证Mach-O文件的签名,并非每次重复读入整个文件,而是把每页的内容都生成一个单独的加密散列值,并存储在__LINKEDIT中。这使得文件每页的内容在读取时都能及时校验并确保不被篡改。

下期预告:iOS启动优化之从exec()到main()

相关文章
相关标签/搜索