【翻譯】XNU:核心

Mac OSX 核心叫做XNU。有關他的說明簡述如下:

Mach

XNU內的程式碼主要是基於Mach 3.0版所開發出來的。Mach本身是卡內基、梅隆大學在1980年代中期一個傳奇性的研究計畫的產物。目前Mach也漸漸成為許多重要系統的核心了。 較早版本的Mach還是一個擁有許多BSD程式碼的單一核心,Mach3.0則是第一個微核心。
XNU的Mach並不是微核心。核心中包含像是BSD的子系統以及其他具代表性的子系統。XNU的Mach還是負擔了一些系統裡較低層次的部份,像是:

  • 核心執行緒支援先佔式多工。
  • 記憶體保護
  • 虛擬記憶體管理
  • 內部程序通訊 ( IPC )
  • 中斷管理
  • 即時支援
  • 核心Debug支援
  • console I/O

如前一章所述,在核心接續接續開機程序之前,bootloader會去呼叫核心的「啟動」程式碼,以進一步進入不同的開機模式。這個低層程式碼是任何一種系統開機程序裡面都會有的。 各種不同的重要變數都會初始化,像是:最大虛擬或物理位址、CPU降速溫度調節閥,同時BAT也會清除,Altivec和快取也都會初始化。之後程式會跳到系統架構的初始程式碼(PowerPC 上的 ppc_init())。
其後程序如下:

  • 一個模組執行緒將會插入,並從中產生一個初始化的執行緒來作為現時執行用的執行緒。
  • 部份CPU終至在執行的程序完成。
  • 「Platform Expert」初始化(PE_init_platform())。而同時設置旗標指出未被初始化的虛擬記憶體。
  • Mach 虛擬記憶體初始化
  • 呼叫machine_startup()程序。這步驟會用到許多系統內部的變數。並呼叫calls setup_main()
  • calls setup_main()會完成很多工作,像是:initializing the scheduler, IPC, kernel extension loading, clock, timers, tasks, threads…等等。最後還會產生一個核心執行緒,叫做tartup_thread,來完成更進一步的其他核心執行緒。
  • startup_thread會製造許多其他的執行緒(靜態的執行緒、負責時間與裝置的執行緒…..等等)。

此時,輪到Mach開始運作執行。
附帶一提,BSD系統會載入相當多APIs,並使用Mach messaging和IPC來讓使用者與系統核心之間轉換資訊。
XNU也提供相當多不同的方式來處理記憶體設置。因為對許多程式設計師來說處理這些問題是相當大的負擔,所以這樣的設計可以讓他們能用更聰明的方式去選擇要使用的API。
這在Mac OSX使用者部份的API處理方式也是一樣的。

BSD

XNU的BSD是以FreeBSD為主要程式碼參考基準(雖然說某些程式碼是參考其他BSD的)。Darwin 7.x(Mac OSX 10.3.x)之後是使用FreeBSD 5.x。如同前面說過的,BSD在這裡並非用在外部(或者說:使用者層級)的部份, 而是系統核心本身的一部份。在某些方面BSD還擔負以下的任務:

  • 程序模型
  • user ids, 權限, 基本安全
  • POSIX API, BSD style system calls
  • TCP/IP stack, BSD sockets, firewall
  • VFS 和 檔案系統
  • System V IPC
  • crypto framework
  • various synchronization mechanisms

XNU雖會統整暫存的快取,但是這東西都會跟Mach的虛擬記憶體綁在一起。
XNU利用一種叫做「漏斗」的同步摘要技術來整合核心中BSD的部份,而核心中會有個用「_flock」作為字尾的東西來將核心中的變數指向「漏斗」,像是kernel_flock或network_flock。當Mach透過呼叫bsd_init()來初始化BSD子系統 時,系統會先將這些漏斗定址(像是核心的漏斗就會定為TRUE)。之後:

  • 核心記憶體運算元會被重新初始。
  • “Platform Expert” 會去偵測有無任何關於BSD啟動的設定
  • VFS 暫存檔列表會重新定址並初始化
  • 程序相依性架構會重新定址並初始化
  • 這裡會創置一個Process 0,而核心程序的變數就是指向Process 0
  • 主機獨立時間和日期也會初始化
  • 統一的暫存快取初始化
  • 不同的 VFS 架構 初始化: the vnode table、檔案系統架構、 the vnode name cache, etc. 每一個現時的檔案系統時間也都初始化
  • mbufs (記憶體暫存、 網路上已使用的記憶體管理) 透過mbinit()初始化
  • 系統環境以及子系統像是 syslog, audit, kqueues, aio, and System V IPC 也都初始化
  • 核心的總 MIB (management information base) 初始化
  • 資料連結介面層初始化
  • Sockets 和各種協定初始化

XNU使用一種特製的核心延伸方式,NKEs(網路核心延伸套件)來讓4.4BSD網路架構可以適用於Mac OSX

  • 開啟核心剖析且 BSD 被當作是IOKit的資源
  • 乙太網路裝置初始化
  • A Mach Zone is initialized for the vnode pager.
  • BSD試著去掛載根目錄檔案系統 (這根目錄系統可以是透過網際網路來掛載,透過NFS掛載MacOSX映像檔–.dmg).
  • devfs 掛載在 /dev
  • kernproc (process 0)創造一個pid 1的新程序(cloned)以作為init (actually mach_init, which starts init)。 mach_init 透過 BSD asynchronous trap handler (bsd_ast())所呼叫出來的bsdinit_task()載入並執行

I/O Kit

I/O Kit,這個XNU核心裡面的物件導向裝置驅動程式韌體跟一般傳統系統是非常不同的。
I/O Kit使用有限制的C++語言子集合(基於Embedded C++)來撰寫,而這系統是由核心的函式庫提供函式。其中,C++在這子集合裡面的限制有:

  • 例外事件
  • 多重繼承
  • 多模組
  • RTTI (run-time type information), I/O Kit 有自己的執行時期系統

I/O Kit也提供裝置驅動程式模組許多相當有用的東西:

  • 各種裝置族群 (ATA/ATAPI, FireWire, Graphics, HID, Network, PCI, USB, HID, …)
  • 各個裝置的物件導向抽象元件可以相互分享使用
  • 隨裝即用以及熱插拔
  • 電源管理
  • 先佔式多工處理, 執行緒, 對稱式多重程序執行, 記憶體保護以及資料管理
  • 驅動程式動態比對以及載入 (multiple bus types)
  • 物件資料追蹤以及資訊建立的資料庫功能(the I/O Registry)
  • 全部系統上可用的I/O Kit classes資料庫 (the I/O Catalog)
  • 衍生API
  • 應用程式架構以及使用者介面與user-space drivers和I/O Kit之間的溝通
  • driver stacking

I/O Kit供給工具包含核心中3個C++函式庫,並可以供載入的驅動程式使用:IOKit.framework、 Kernel/libkern 與 Kernel/IOKit。藉著擷取各種不同的硬體、軟體之間的動態關係,I/O Kit包含模組化、層級化執行時期架構, 而這就是底層硬體的抽象化的現時情況。
各種不同的工具像是:ioreg, ioalloccount, ioclasscount, iostat, kextload, kextunload, kextstat, kextcache…等,讓我們可以操控I/O Kit。舉例來說,下列示範就能顯示出核心動態載入的物件:

% kextstat
Index Refs Address Size Wired Name (Version)
1 1 0x0 0x0 0x0 com.apple.kernel (7.2)
2 1 0x0 0x0 0x0 com.apple.kpi.bsd (7.2)
3 1 0x0 0x0 0x0 com.apple.kpi.iokit (7.2)
4 1 0x0 0x0 0x0 com.apple.kpi.libkern (7.2)

下列指令就會顯示出I/O Kit登錄檔的細節:

% ioreg -l -w 0
+-o Root
| {
| “IOKitBuildVersion” = “IOKit Component Version 7.2:
Thu Dec 11 16:15:20 PST 2003;
root(rcbuilder):RELEASE_PPC/iokit/RELEASE

| “IONDRVFramebufferGeneration” = <0000000200000002>

/* thousands of lines of output */

Platform Expert

Platform Exper是個能知道現在系統正在跑甚麼平台的物件(你能先把他看成是個驅動程式)。I/O Kit會登錄一個節點給Platform Exprt,而這節點會去載入正確的驅動程式給平台,甚至更進一步去發現系統上正在執行的匯流, 並為每一個匯流登錄一個節點。然後I/O Kit會為每個匯流節點載入正確的驅動程式,並將發現的裝置與節點連結起來。總結來說,Platform Expert負責:

  • 建造裝置樹狀結構
  • 分析開機程序內容
  • 辨別機器硬體 (包含硬體與bus clock 速度)
  • 如果發生kernel panic,則初始化其使用者介面

libkern and libsa

如前面所述,I/O Kit是使用C++的受限制的子集合,而這東西內容主要是libkern,提供以下的服務:

  • 動態元件整合 、建構、反建構(including data structures such as Arrays, Booleans, Dictionaries, …)
  • 自動化作用、 混合式方程式 (bcmp(), memcmp(), strlen(), …)
  • 追蹤即時class的預覽功能
  • 避免”Fragile Base Class Problem”

libsa則提供許多方程式來處理多樣的目的:binary搜尋、symbol、 remanglinggraphs, catalogs, kernel extension management, sorting, patching vtables…等等。

Leave a Reply

Be the First to Comment!

Notify of
avatar
wpDiscuz