目錄
- 簡述
- Mach
- 任務(wù)與線程
- 端口
- 虛擬地址
- 任務(wù)地址空間
- BSD
- I/O kit
簡述
XNU內(nèi)核是iOS的核心,與OS X版本幾乎沒有區(qū)別,是由三個(gè)主要部分組成的一個(gè)分層體系結(jié)構(gòu)。大致結(jié)構(gòu)如圖所示,畫得有點(diǎn)丑。

該內(nèi)核的內(nèi)環(huán)是Mach層,該層僅僅提供了例如調(diào)度、IPC等基礎(chǔ)服務(wù)。這些服務(wù)都是為內(nèi)核提供的。
第二個(gè)部分是BSD層,BSD層主要是為用戶層面提供一些接口,為一些操作提供支持,網(wǎng)絡(luò)、進(jìn)程管理、文件系統(tǒng)。
最后一個(gè)部分就是I/O Kit,顧名思義,為設(shè)備的驅(qū)動程序提供面向?qū)ο蟮目蚣堋?/p>
由于作者知識有限,只能把一些知道的知識點(diǎn)陳述出來,因此知識點(diǎn)看起來會有一些零散難以理解。另文章難免會出現(xiàn)一些錯漏的地方,還望指出以便于及時(shí)更改防止誤導(dǎo)他人。
Mach
Mach前面已經(jīng)說過了,為高層提供底層服務(wù)。關(guān)于Mach的官方文檔在這里(建議翻墻打開)
Mach提供了一組簡單又強(qiáng)大的抽象用于實(shí)現(xiàn)基礎(chǔ)服務(wù)。
- 任務(wù)(Task).每一個(gè)任務(wù)都包含著一個(gè)虛擬空間、一個(gè)端口命名空間以及一個(gè)或多個(gè)線程,跟進(jìn)程類似。(下文的進(jìn)程和任務(wù)可能有些混亂,但不耽誤理解)
- 線程(Thread).CPU執(zhí)行最小單位。
- 地址空間(Address space).Mach使用地址空間與內(nèi)存管理器,實(shí)現(xiàn)了不連續(xù)的虛擬地址空間以及共享內(nèi)存的概念。
- 內(nèi)存對象(Memory object).它是內(nèi)存管理的內(nèi)部單元。
- 端口(Ports).單工通信通道,只能發(fā)送或者通過端口權(quán)限訪問。
- IPC
- 時(shí)鐘(Time)
下面就講一下Mach中經(jīng)常被提及的一點(diǎn)概念,IPC與消息可以移步這里。
任務(wù)與線程
OS X進(jìn)程,POSIX thread(pthread)都是基于Mach中任務(wù)與線程實(shí)現(xiàn)的。任務(wù)為線程提供資源,這種靠任務(wù)劃分的方式大大提高了資源的共享性。
對于一個(gè)線程來說,它
- 是任務(wù)的控制流點(diǎn)。
- 可以訪問任務(wù)中所有的元素。
- 可以與同任務(wù)中另一線程并行執(zhí)行。
- 有自己的狀態(tài),包括處理器狀態(tài)以及自己的棧。
對于任務(wù)來說,它
- 是一個(gè)資源的集合體,它的資源除了地址空間以外,可以通過端口獲取。如果另一個(gè)任務(wù)需要訪問該資源,它直接傳遞端口權(quán)限就好。
- 提供一個(gè)不連續(xù)的地址空間。這個(gè)空間的部分可以通過繼承或者外部內(nèi)存管理器來共享出去。
- 包含一個(gè)或多個(gè)線程。
端口
端口是請求服務(wù)的客戶端與提供服務(wù)的服務(wù)器之間單向通信的端點(diǎn),除了任務(wù)地址空間以外,所有其他Mach資源都可以通過端口訪問。一個(gè)端口可以接收多個(gè)發(fā)送者的消息,但每個(gè),端口只能有一個(gè)接收器。換句話說就是禁止群發(fā)。
為了保證端口安全,防止資源外泄,端口還有保護(hù)機(jī)制,稱之為端口權(quán)限。為了與端口交互,任務(wù)必須要有正確的端口權(quán)限。端口權(quán)限與任務(wù)相關(guān),因此,任務(wù)里的所有線程都共享相同的端口權(quán)限。權(quán)限還可以在任務(wù)之間復(fù)制和移動,但有一點(diǎn),如果在父進(jìn)程中fork出子進(jìn)程,那么子進(jìn)程是沒有和父進(jìn)程一樣的權(quán)限的。關(guān)于端口的權(quán)限,定義在mach/port.h中,用xcode就能看到。
typedef natural_t mach_port_right_t;
#define MACH_PORT_RIGHT_SEND ((mach_port_right_t) 0)//允許發(fā)送消息
#define MACH_PORT_RIGHT_RECEIVE ((mach_port_right_t) 1)//允許接收消息
#define MACH_PORT_RIGHT_SEND_ONCE ((mach_port_right_t) 2)//允許發(fā)送消息一次
#define MACH_PORT_RIGHT_PORT_SET ((mach_port_right_t) 3)//面向一組端口接收或發(fā)送消息
#define MACH_PORT_RIGHT_DEAD_NAME ((mach_port_right_t) 4)//無效或銷毀的權(quán)限
#define MACH_PORT_RIGHT_LABELH ((mach_port_right_t) 5)
#define MACH_PORT_RIGHT_NUMBER ((mach_port_right_t) 6)
虛擬地址
要說虛擬地址,得先從虛擬內(nèi)存講起,虛擬地址指向的內(nèi)存就是虛擬內(nèi)存。由于計(jì)算機(jī)系統(tǒng)的RAM資源有限,當(dāng)系統(tǒng)分配的內(nèi)存太多時(shí),RAM很有可能不夠用,因此現(xiàn)代操作系統(tǒng)都使用一種虛擬內(nèi)存技術(shù)來解決RAM不夠的問題。
虛擬內(nèi)存,顧名思義就是虛擬的內(nèi)存,這樣進(jìn)程就可以分配和使用比系統(tǒng)RAM還要多的內(nèi)存,它把超過RAM的地址空間放入到外部存儲器(硬盤)上??墒菃栴}又來了,CPU不能直接訪問外部存儲器的地址。因此,操作系統(tǒng)必須在外部存儲器和RAM之間交換數(shù)據(jù),以便于CPU能訪問外部存儲器的數(shù)據(jù)。一般來說,進(jìn)程只需要使用分配的總內(nèi)存的一小部分,我們把這部分分為工作集。由于硬盤的讀取速度遠(yuǎn)遠(yuǎn)小于RAM的讀取速度,因此,為了忽略虛擬內(nèi)存給執(zhí)行速度帶來的影響,如果進(jìn)程需要訪問硬盤地址,操作系統(tǒng)會將硬盤存儲的數(shù)據(jù)先讀取到RAM中,如果RAM已經(jīng)滿了,沒有空間可以放入數(shù)據(jù),那么系統(tǒng)會先把RAM的一些數(shù)據(jù)放入到硬盤中,騰出空間再讀取。
談到虛擬內(nèi)存,那就不得不談起分頁。上文說到RAM會與硬盤的數(shù)據(jù)會進(jìn)行交換。分頁技術(shù)將物理內(nèi)存(RAM+硬盤)分成固定長度的塊,稱為頁幀,將虛擬內(nèi)存也劃分成固定長度的塊,稱為頁。每頁與每幀的大小相同,這樣就可以將每頁映射到每幀中。

如圖所示,虛擬內(nèi)存中的每一頁都對應(yīng)著物理內(nèi)存的每一幀。既然將進(jìn)程分配的空間"打散"了,那么進(jìn)程分配的物理空間就可以不連續(xù),進(jìn)程分配的空間只需要在虛擬空間中連續(xù)就好,虛擬空間映射成的物理空間可以七零八落分配在各個(gè)地方,這樣做就解決了物理空間碎片化的的問題,提高了物理空間的利用率。
可能到這里有人會問了,進(jìn)程怎么知道自己分配的內(nèi)存是在RAM中還是在硬盤中。在進(jìn)程啟動的時(shí)候,操作系統(tǒng)會給它創(chuàng)建一個(gè)表,用于保存進(jìn)程的虛擬空間地址以及其對應(yīng)的物理地址的映射關(guān)系,這個(gè)表被稱為分頁表。這個(gè)表中的每一項(xiàng)對應(yīng)進(jìn)程地址空間中的每一頁,換句話說它也和物理空間幀一一對應(yīng)。這個(gè)分頁表的項(xiàng)還包含著訪問控制位(判斷是否只讀)與標(biāo)志位(在RAM還是硬盤)。也就是說,有了進(jìn)程的虛擬地址,系統(tǒng)就可以根據(jù)分頁表中的映射關(guān)系找到它的物理地址,無論它在哪。
其實(shí)上面扯了那么多,iOS根本就不支持外部存儲器(硬盤),但是這種內(nèi)存分配方式(虛擬映射物理)還是有好處的,把虛擬內(nèi)存化整為零可以大大的減少物理內(nèi)存的碎片的產(chǎn)生。另一個(gè)好處就是進(jìn)程可以完全使用自己的虛擬內(nèi)存空間,不用在乎物理空間,當(dāng)然這只是理論上的完全使用,具體原因見下文。
任務(wù)地址空間
在用戶每一個(gè)進(jìn)程的虛擬內(nèi)存中,都有一段空間是專門為內(nèi)核保留的。具體原因見巨內(nèi)核優(yōu)點(diǎn)。
在64-bit架構(gòu)中,內(nèi)核預(yù)留的空間跟32-bit不太一樣。64-bit理論上的地址空間可以使用0-0xffffffffffffffff(2^64)。但是由于當(dāng)時(shí)硬件并不能支持64位尋址空間,因此用戶只能使用48位的尋址空間,后來就一直延續(xù)下來了。既然在64-bit下只能使用48位尋址空間,那么必須要用一些規(guī)范來對地址進(jìn)行約束。約定地址第48-63位必須與47位相等。這就是規(guī)范形式地址,因此64位的地址空間被分為了兩個(gè)部分。0-0x00007fffffffffff,0xffff800000000000-0xffffffffffffffff。這兩個(gè)部分每一個(gè)部分都是128T,高128T字節(jié)預(yù)留給內(nèi)核,低128T字節(jié)屬于用戶自己使用的,用戶如果意圖訪問虛擬空間中的內(nèi)核地址,則會報(bào)錯。如果訪問了中間非規(guī)范形式的地址,硬件會報(bào)錯。映射關(guān)系如圖所示。

BSD
BSD層位于Mach上層,但還是處于內(nèi)核之中。它實(shí)現(xiàn)了很多操作系統(tǒng)的核心功能,這些功能的實(shí)現(xiàn)都建立在Mach提供的服務(wù)之上。BSD層提供了如下服務(wù):
- 進(jìn)程和用戶管理
- 文件管理
- 安全
- 內(nèi)存管理
- 驅(qū)動程序
- 網(wǎng)絡(luò)連接
- 系統(tǒng)調(diào)用
I/O Kit
I/O Kit是一個(gè)面向?qū)ο蟮目蚣?,用于編寫設(shè)備驅(qū)動程序及其他內(nèi)核擴(kuò)展。I/O Kit對系統(tǒng)硬件進(jìn)行了抽象,提前定義了許多類型的硬件基類,可以讓新的驅(qū)動程序去繼承這些基類,從而實(shí)現(xiàn)代碼的高度重用。