iOS App启动流程——理论知识篇

栏目: IOS · 发布时间: 5年前

内容简介:Mach-O文件可以分成segment。通常大写字母表示,例如

一、Mach-O结构

1. Mach-O术语:

  • Executable (可执行文件)
  • Dylib (动态库)
  • Bundle —— iOS特有的动态库,不可链接,只能运行时使用dlopen()

Image —— Executable、Dylib、Bundle都是 Image

Framework —— 带有特殊目录结构的Dylib,用来保存资源和头文件。

2. Mach-O内部结构

Mach-O文件可以分成segment。通常大写字母表示,例如 __TEXT , __DATA , __LINKEDIT

iOS App启动流程——理论知识篇

segment的大小由硬件决定的,是页大小的整数倍。arm64的页大小是16KB,其他的是4KB。

  • __TEXT :__TEXT位于文件的头部,包含Mach header,机器指令以及readonly的常量,例如c字符串。
  • __DATA :readwrite,包含全局变量
  • __LINKEDIT :包含函数的名称和地址相关的信息

3. Mach-O通用文件

为32位和64位设备编译会分别获得一个Mach-O文件。将两个文件合并后会获得一个Mach-O通用文件,可以同时运行在32位和64位的设备上。

iOS App启动流程——理论知识篇

Fat Header记录其中的架构以及偏移位置。

二、虚拟内存

every problem can be solved by adding a level of indirection.

虚拟内存解决的问题是,多进程系统如何管理物理内存。

每个进程是由物理内存页映射的逻辑地址空间。 这种映射并 不是一一对应的 ,例如 有的逻辑地址不对应物理内存空间 ,也有 可能不同的逻辑地址对应着相同的物理内存

Page fault

有些逻辑地址没有对应的内存空间,当程序访问该逻辑地址时,会触发page fault。

此时内核就会停下当前的线程,来xxxxx

共享内存

不同的进程中的逻辑地址空间可以映射相同的物理内存空间,这两个进程共享内存中的内容。

file backed pages

可以通过mmap()调用,告诉虚拟内存,将文件中的某一片段映射到进程中的某段地址空间,而不是将整个文件都读进内存。没当第一次访问之前没有访问过的地址空间,都会触发一个page fault,内核会从文件中读取一页。从而实现了文件的懒读取,提升加载速度。

copy on write

当两个进程访问__DATA内容的时候,一个进程只读,一个进程想要写,这是就会出现copy on write。内核会将这一页copy到新的地址空间,然后重新映射。这时,进程都有自己copy出来的这一页。只读的那一页是clean page,拷贝出来的进行写操作的这一页叫做dirty page。dirty page意味着其中包含了进程相关的信息。对于clean page,内核之后可以重新生成,重新从硬盘中读取。dirty page代价更为昂贵。

加载动态库的过程

iOS App启动流程——理论知识篇

假设动态库的大小为8页,两个进程需要加载这个动态库。

进程1:

  1. dyld需要加载Mach-O的header,即图中RAM1。发现没有映射,所以触发page fault,将RAM1读取到物理内存中,然后映射到进程1的虚拟内存中。
  2. dyld读取Mach-O header,然后发现还需要一些信息在__LINKEDIT中。此时加载__LINKEDIT中的信息,触发page fault,将RAM2读取到物理内存中,然后映射到进程1的虚拟内存中。
  3. dyld读取__LINKEDIT内容,需要修改__DATA page的内容使动态库可运行。此时同上,加载__DATA中的信息,触发page fault,将RAM3读取到物理内存中,然后映射到进程1的虚拟内存中。
  4. 当dyld要往__DATA page中写内容的时候,就会触发copy on write。RAM3就变成的dirty page。

进程2:

  1. dyld需要加载Mach-O的header,即图中RAM1。内核会告诉dyld,内存中已经有这个页了。直接映射到进程2的虚拟内存中,无需IO。
  2. 同理,RAM2也是。
  3. 读取RAM3的时候,内核会查看RAM3的clean page依然在内存中,如果在,直接映射,如果不在,重新加载进内存。当dyld需要往__DATA page中写内容的时候,就会触发copy on write。RAM3就变成的dirty page。

只有dyld加载动态库的时候,才会需要__LINKEDIT,一旦完成后,__LINKEDIT中的内容可以回收。

此时,一共用了2个dirty page 和1个clean page。如果是直接读取整个文件到内容中,则一共产生了16个dirty page!

两个安全技术

  1. ASLR(address space layout randomization):地址空间布局随机化,将加载地址随机化。
  2. code sign:为了在运用时验证文件,整个文件在运行时重新读取,所以Mach-O中的每一页都有独立的code sign,存放在__LINKEDIT中。这样就能保证每一页都没有被篡改。

参考


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

美铁之战

美铁之战

[英]帕特里克·蒂利 / 黑曜、超侠 / 百花文艺出版社 / 2018-9 / 44.80元

本书的故事发生在未来,一场核战毁灭了北美大陆上的人类文明,残存下来的人类分化成两拨:生活在地面上退化到刀耕火种时代的平原人;躲藏在地下苟延残喘的沙穴人。几百年后,当保留着战前文明的沙穴人尝试着登上地面,和平原人的同室操戈将不可避免地上演……一起来看看 《美铁之战》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试