iOS App啓動流程——理論知識篇

1、Mach-O結構

1. Mach-O術語:

  • Executable(可執行文件)
  • Dylib(動態庫)
  • Bundle —— iOS特有的動態庫,不可連接,只能運行時使用dlopen()

Image —— Executable、Dylib、Bundle都是 Image架構

Framework —— 帶有特殊目錄結構的Dylib,用來保存資源和頭文件。app

2. Mach-O內部結構

Mach-O文件能夠分紅segment。一般大寫字母表示,例如__TEXT, __DATA, __LINKEDITide


segment的大小由硬件決定的,是頁大小的整數倍。arm64的頁大小是16KB,其餘的是4KB。函數

  • __TEXT:__TEXT位於文件的頭部,包含Mach header,機器指令以及readonly的常量,例如c字符串。
  • __DATA:readwrite,包含全局變量
  • __LINKEDIT:包含函數的名稱和地址相關的信息

3. Mach-O通用文件

爲32位和64位設備編譯會分別得到一個Mach-O文件。將兩個文件合併後會得到一個Mach-O通用文件,能夠同時運行在32位和64位的設備上。spa


Fat Header記錄其中的架構以及偏移位置。.net

2、虛擬內存

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

虛擬內存解決的問題是,多進程系統如何管理物理內存。線程

每一個進程是由物理內存頁映射的邏輯地址空間。這種映射並不是一一對應的,例如有的邏輯地址不對應物理內存空間,也有可能不一樣的邏輯地址對應着相同的物理內存3d

Page faultcdn

有些邏輯地址沒有對應的內存空間,當程序訪問該邏輯地址時,會觸發page fault。blog

此時內核就會停下當前的線程看下一步應該如何作。

共享內存

不一樣的進程中的邏輯地址空間能夠映射相同的物理內存空間,這兩個進程共享內存中的內容。

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代價更爲昂貴。

加載動態庫的過程


假設動態庫的大小爲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!


main()以前



參考

相關文章
相關標籤/搜索