Fuchsia系列博客(三) Zircon內核核心概念
Fuchsia系列博客(三) Zircon內核核心概念
- 翻譯自(不是嚴格翻譯):
https://fuchsia.googlesource.com/fuchsia/+/master/zircon/docs/concepts.md
介紹
Zircon內核負責管理大量不同類型的對象.
那些實現了Dispather
介面的對象可以通過系統調用直接訪問, 這些對象在kernal/object
目錄下, 包括許多自包含的高級對象, 和一些對lk原語
的封裝.
系統調用(System Call)
用戶空間的代碼通過系統調用與內核對象交互, 甚至可以說, 絕大多數是通過Handles(句柄)
.(譯者按: 下文中, Handle一詞一律不翻譯.)Handle實際上是一個32bit 的整數(zx_handle_t
類型).
在系統調用被實際執行前, 內核將進行三項檢查.
- 檢查Handle參數是否指向調用process進程的
Handle表
中存在的實際句柄. - 檢查Handle的類型是否正確. (例如:將
Thread Handle
傳給需要Event Handle
的系統調用會導致錯誤.) - 檢查Handle是否具有所請求的操作許可權.
從訪問限制的角度看, 系統調用分為三大類:
- 無限制系統調用. 可以被任何thread(線程)調用, 極少數的系統調用屬於這一類, 例如:
zx_clock_get()
和zx_nanosleep()
. - 消費一個Handle的系統調用. Handle作為第一個參數, 代表系統調用作用的對象. 絕大多數的系統調用屬於該類, 例如:
zx_channel_write()
和zx_port_queue()
. - 無需Handle並創造新對象的系統調用. 他們的調用以及訪問限制由包含該process(進程)的Job(作業)控制.例如:
zx_event_create()
和zx_channel_create()
.
系統調用由libzircon.so
提供, libzircon.so
是一個由內核提供的"虛擬"共享庫, 也被稱之為virtual Dynamic Shared Object
或者vDSO
. 系統調用都是C ELF ABI
形式的函數: zx_名詞_動詞
或者zx_名詞_動詞_直接對象
.
系統調用由syscall.abigen
定義, 並且由abigen tool
處理頭文件和libzircon
中與內核libsyscalls
連接的膠水代碼.
Handles(句柄) 和 Rights(許可權)
- 可以有很多分佈在一個或多個進程(process)中的Handle指向同一個對象.
- 對於絕大多數對象來說, 最後一個指向他的Handle被關閉, 該對象也隨之消亡, 抑或進入一種無法撤銷的最終狀態.
- 有兩種方式把句柄在進程之間轉移, 第一種是調用
zx_channel_write()
把Handle寫入Channel(通道), 另一種方法是調用zx_process_start()
, 把這個Handle傳遞給新進程的第一個線程. - Rights負責管理相關Handle和Object可能進行的任何行為, 指向同一對象的不同Handle完全可能用有不同的許可權.
zx_handle_duplicate()
和zx_handle_replace()
系統調用可以產生指向該對象的新的Handle, 並且可以選擇性減少新Handle的許可權.zx_handle_close()
負責關閉Handle, 如上所述, 該方法也將銷毀對象, 如果關閉Handle後再沒有Handle持有該對象.zx_handle_close_many()
與其相似, 只是關閉一個Handle數組中的所有Handle.
內核對象ID (Kernel Object IDs)
每個對象都有個內核對象ID
, 簡稱koid
. 這是一個64位整數, 是對象的唯一標識符, 並且在系統運行的週期內是唯一的. 這意味著"koid"永遠不會被重用.(譯者按: 真的不會被用完嗎? 0.0)
ZX_KOID_INVALID
: 值是0
, 用來做null
. ZX_KOID_KERNEL
: 內核自己的唯一koid. 內核只用63個位(真的是很多了)生成koid. 用戶可以通過設置最高有效位, 分配剩餘的koid. 內核分配koid的順序沒有被指定, 並且可能發生變化. 人工分配的koid提供了更多可能:例如辨別人工對象, 跟蹤虛擬線程, 這些都可以被各種工具使用. 而對於每個程序如何分配人工koid, 本文檔不做任何限制和規則約束.
運行中的代碼: 作業(Jobs), 進程(Processes)和線程(Threads)
線程代表地址空間中實際執行的線程(CPU 寄存器, 棧等), 線程的地址空間被他們所在的進程擁有.
進程又由作業擁有, 作業定義了各種各樣的資源限制. 作業又被它的父作業擁有, 層層傳遞, 直到根作業(Root Job). 根作業在系統啟動時由內核創建, 進而傳遞給第一個用戶空間進程--userboot. 沒有作業的Handle, 進程中的線程不可能創建另一個進程或者另一個作業.程序如何載入
由內核空間上層的用戶空間設施和協議規定. 請參閱:zx_process_create()
, zx_process_start()
, zx_thread_create()
和 zx_thread_start()
.
消息傳遞: 套接字(Sockets)和通道(Channels)
套接字和通道都是用於雙向通信的IPC對象, 創建套接字或者通道將返回兩個對象, 一邊一個.
套接字是面向流的編程模型, 允許短讀和短寫, 數據以一個或多個位元組作為單元傳輸. 通道是面相數據報的編程模型, 擁有最大長度限制ZX_CHANNEL_MAX_MSG_BYTES
, 還擁有消息句柄數量限制, 即ZX_CHANNEL_MAX_MSG_HANDLES
. 不支持短寫和短讀 -- 嚴格判定每個消息是否合適. 當Handle被寫入通道時, 他們從發送端進程移除. 當Handle從通道讀取時, 他們被加入到接收端進程. 在傳輸過程中, Handle並未消失, 這意味著它指向的對象仍舊存在. 然而, 如果通道的終點被關閉, 傳輸中的消息將會被丟棄, 所有指向該消息的句柄都會被關閉.
請參閱: zx_channel_create()
, zx_channel_read()
, zx_channel_write()
, zx_channel_call()
, zx_socket_create()
, zx_socket_read()
和 zx_socket_write()
.
對象(Objects)和信號(Signals)
對象有至多32種信號(zx_signals_t
類型, 由ZX_SIGNAL
定義), 這些信號代表對象當前狀態的信息. 例如: 通道(Channel)和套接字(Socket), 可能是READABLE
或者WRITABLE
的. 進程(Process)和線程(Thread)可以是TERMINATED
, 等等...
Signals
獲取更多信息.
等待:等待一個, 等待許多, 等待埠
線程可以使用zx_object_wait_one()
等待一個信號Handle, 或者用zx_object_wait_many()
等待一組信號Handle.
這兩種方法都允許超時設置, 一旦超時, 即使沒有響應信號, 方法也會返回.
由於timer slcak
(計時器鬆弛)的存在, 超時設置將會有誤差, 並不一定在設置的時間返回. 詳情請見timer slack
. 如果一個線程想要等待大量的Handle, 那不如使用埠(Port). 埠是一個對象, 可以被其他對象綁定, 這樣, 當其他對象上的信號到達時, 埠就會收到與這些信號的信息相關的數據包.
請參閱:zx_port_create()
, zx_port_queue()
, zx_port_wait()
和 zx_port_cancel()
.
事件 (Events), 事件對 (Event Pairs)
事件是最簡單的對象,除了其活動信號集合之外沒有其他狀態。
事件對是可以相互發信號的一對事件之一。事件對的一個有用屬性是當一側消失(所有句柄都已關閉)時,PEER_CLOSED信號在另一側被斷言。(譯者按: 量子糾纏?)
請參閱:zx_event_create()
和 zx_eventpair_create()
.
共享內存: 虛擬內存對象(VMO)
虛擬內存對象代表一組物理內存頁面,或"潛在"的頁面(可以按需創建/填充的頁面).
虛擬內存對象可以通過zx_vmar_map()
來映射到進程的地址空間, 用zx_vmar_unmap()
取消該映射. 被映射頁面的許可權可由zx_vmar_protect()
來調整.
VMO也可以通過zx_vmo_read()
和zx_vmo_write()
直接讀取和寫入. 因此,對於一次性操作, 如"創建一個VMO, 將數據集寫入其中, 並將其交給另一個進程使用", 可以避免將它們映射到地址空間的成本。
地址空間管理
虛擬內存地址區域(VMAR)提供了管理進程地址空間的抽象。在進程創建時,將向進程創建者提供root VMAR
的句柄。該句柄指的是跨越整個地址空間的VMAR
。這個空間可以通過zx_vmar_map()
和zx_vmar_allocate()
介面進行分割. zx_vmar_allocate()
可以用於生成新的VMAR(稱為subregions
或children
), 這可以將地址空間的某些部分組合在一起。
請參閱: zx_vmar_map()
, zx_vmar_allocate()
, zx_vmar_protect()
,zx_vmar_unmap()
和 zx_vmar_destroy()
.
Futexes
Futexes
是與用戶空間原子操作一起使用的內核原語, 用於實現高效的同步原語 -- 例如, 競爭情況下的互斥鎖實現, 只需要一個系統調用. 通常只有標準庫的實現者對他們感興趣. Zircon
的libc
和libc++
為互斥體, 條件變數等以Futexes的形式提供了C11
, C ++
和pthread
的API.
請參閱: zx_futex_wait()
, zx_futex_wake()
和 zx_futex_requeue()
.
推薦閱讀: