問題
開始正文前:先拋出幾個問題,帶著疑問閱讀下面的文章,應該會更有收獲。
- iOS 系統架構可以分為幾層?
- Darwin 層又可以分為幾部分?能否簡單介紹下各部分?
- IPC 是什么?,有哪些常見 IPC?iOS 中一般采用什么方式進行 IPC?能否舉一些 IPC 的例子出來?
- 能否介紹一下宏內核、微內核、混合內核以及各自的優劣?
1 iOS 系統架構
上一次問答在說到 iOS 事件響應流程時,提到了 iOS 系統框架中的 IOKit 和 SpringBoard。今天就深入展開介紹一下 iOS 的系統框架。
iOS 系統可以分為四層,從下往上介紹:
- 第一層是 Darwin 層,是操作系統的核心,屬于操作系統的內核態,包括了系統內核 XNU,驅動等,是開源的,可在 opensource.apple.com 找到。
- 第二層是核心框架層,包括 Metal、OpenGL 等。
- 第三層是應用框架層,比如 Cocoa Touch 框架。
- 第四層是用戶體驗層,包括用戶能接觸到的圖形應用,如 SpringBoard(桌面系統,統一管理和分發系統接收到的觸摸事件)、Spotlight。
上面提到 Darwin 層屬于操作系統的內核態,而其余的三層,核心框架層、應用框架層、用戶體驗層屬于用戶態。
Darwin 的內核是 XNU,全稱 'XNU’s Not UNIX'。下面會著重介紹一下 XNU。如上圖所示,XNU 主要由以下三項組成:
- Mach
- BSD
- IOKit
2 Mach
2-1 Mach 基本介紹
Mach 是 XNU 內核的內環,屬于微內核,只提供了處理器調度、進程間通信(IPC)、內存保護、虛擬內存管理、進程和線程的抽象等功能。
2-2 IPC
Mach 的核心功能是 IPC(Inter-Process Communication)。在 Mach 中,所有東西都是屬于對象范疇的,比如進程、線程、虛擬內存。對象間是不能直接相互調用的,必須通過消息傳遞的方式實現,消息會在兩個端口之間傳遞,也就是基于 mach port。當處于用戶態的核心框架層、應用框架層、用戶體驗層需要進行系統調用的時候,會調用 mach_msg_trap()
觸發陷阱機制,切換到內核態,內核態中實現 mach_msg()
函數完成最后的工作。具體過程如下:
RunLoop 的核心就用到了 mach_msg()
,當沒有接收到 port 消息時,內核會將線程置為等待狀態,節省資源。
在 iOS 屏幕渲染過程,同樣會利用到 IPC。
在 Xcode 中運行 App 時,點擊調試欄中的暫停按鈕,也可以看到主線程調用棧停留在 mach_msg_trap()
。
在 iOS 中,剪貼板(Pasteboard)同樣屬于進程間通信方式的范疇。
(IPC 參考鏈接)[https://nshipster.com/inter-process-communication/]
3 BSD
Mach 本身提供的 API 有限,額外功能需要 BSD 來實現,BSD 可以看做圍繞 Mach 層的一個外環,提供了更高層次的抽象,提供了進程管理、文件系統、網絡諸多功能。屬于宏內核。
4 IOKit
IOKit 是硬件驅動程序的運行環境,包括電源、內存、CPU 等信息。為設備驅動提供了一個面向對象(C++)的框架。
這里再簡單講一下 Darwin 層 IOKit、用戶體驗層中的 SpringBoard 在觸摸事件中起到的作用:
- 用戶觸摸屏幕,屏幕硬件將事件通過 mach port 發送給 IOKit
- IOKit 將觸摸事件封裝成 IOHIDEvent 對象,通過 mach port (進程端口通信)傳遞給 用戶體驗層的 SpringBoard
- SpringBoard 會判斷,如果在桌面,則交由系統進程去消耗
- 如果是在應用中發生,將觸摸事件通過 IPC 傳遞給對應應用(source1),source1 喚醒 RunLoop,將事件分發給 source0,_UIApplicationHandleEventQueue 將 IOHIDEvent 包裝成 UIEvent 向下分發
5 Mach、BSD 和微內核、宏內核、混合內核
前面的內容提到 Mach 屬于微內核,BSD 屬于宏內核,那這樣安排的用意是什么呢?這里簡單解釋一下。
在微內核中,用戶服務和內核服務是在不同的地址空間實現的。因此在用戶態如果要進行系統調用的話,需要通過消息傳遞的方式進行通信,隨之帶來的缺點是消息傳遞會造成執行速度變慢。
優點:
- 健壯性:用戶服務和內核服務是相互獨立的,用戶服務的崩潰不會影響到內核服務。
- 擴展性強:添加新的功能,只需要建立一個新的服務到用戶空間即可,內核空間不需要做出修改。
- 占用內存小:內核是常駐內存當中,因為內核服務只有一些最基本的功能,所占內存空間小。
而在宏內核中,用戶服務和內核是在同一空間中實現的。因此不需要經過消息傳遞,執行速度比微服務快。但是微內核所擁有的優點,則變成了宏內核的劣勢。
既然微內核和宏內核,各自有優點,那何不把兩個結合一下,各取所長呢。這就是混合內核了。大致做法是,混合內核會把一些不經常使用的內核模塊從內核中移出,從而降低了內核的復雜程度。
XNU 采用的就是微內核 Mach 和宏內核 BSD 的混合內核。