SYSINIT是一個通用的調用排序與分別執行機制的框架。FreeBSD目前使用它來進行內核的動態初始化。SYSINIT使得FreeBSD的內核各子系統能夠在內核或模塊動態加載連接時被重整、添加、刪除、替換,這樣,內核和模塊加載時就沒必要去修改一個靜態的有序初始化安排表甚至從新編譯內核。這個體系也使得內核模塊(如今稱爲KLD能夠與內核不一樣時編譯、連接、在引導系統時加載,甚至在系統運行時加載。這些操做是經過"內核連接器"(kernel linker)和"連接器集合"(linker set)完成的。連接器集合(Linker Set)是一種連接方法。這種方法將整個程序源文件中靜態申明的數據收集到一個可鄰近尋址的數據單元中。 SYSINIT要依靠連接器獲取遍及整個程序源代碼多處申明的靜態數據並把它們組成一個彼此相鄰的數據塊。這種連接方法被稱爲"連接器集合"(linker set)。SYSINIT使用兩個連接器集合以維護兩個數據集合,包含每一個數據條目的調用順序、函數、一個會被提交給該函數的數據指針。
SYSINIT按照兩類優先級標識對函數排序以便執行。第一類優先級的標識是子系統的標識,給出SYSINIT分別執行子系統的函數的全局順序,定義在中的枚舉sysinit_sub_id內。第二類優先級標識在子系統中的元素的順序,定義在中的枚舉sysinit_elem_order內。 有兩種時刻須要使用SYSINIT:系統啓動或內核模塊加載時,系統析構或內核模塊卸載時。內核子系統一般在系統啓動時使用SYSINIT的定義項以初始化數據結構。例如,進程調度子系統使用一個SYSINIT定義項來初始化運行隊列數據結構。設備驅動程序應避免直接使用SYSINIT(),對於總線結構上的物理真實設備應使用DRIVER_MODULE()調用的函數先偵測設備的存在,若是存在,再進行設備的初始化。這一系統過程當中,會作一些專門針對設備的事情,而後調用SYSINIT()自己。對於非總線結構一部分的虛設備,應改用DEV_MODULE()。
api
接口 數據結構
頭文件 框架
<sys/kernel.h> ide
宏 函數
SYSINIT(uniquifier, subsystem, order, func, ident) ui
SYSUNINIT(uniquifier, subsystem, order, func, ident) spa
宏SYSINIT()在SYSINIT啓動數據集合中創建一個SYSINIT數據項,以便SYSINIT在系統啓動或模塊加載時排序並執行其中的函數。SYSINIT()有一個參數uniquifier,SYSINIT用它來標識數據項,隨後是子系統順序號、子系統元素順序號、待調用函數、傳遞給函數的數據。全部的函數必須有一個恆量指針參數。
SYSINIT()的例子 指針
#include <sys/kernel.h> htm
void foo_null(void *unused) 排序
{
foo_doo();
}
SYSINIT(foo, SI_SUB_FOO, SI_ORDER_FOO, foo_null, NULL);
struct foo foo_voodoo = {
FOO_VOODOO;
}
void foo_arg(void *vdata)
{
struct foo *foo = (struct foo *)vdata;
foo_data(foo);
}
SYSINIT(bar, SI_SUB_FOO, SI_ORDER_FOO, foo_arg, &foo_voodoo);
注意,SI_SUB_FOO和SI_ORDER_FOO應當分別在上面提到的枚舉sysinit_sub_id和sysinit_elem_order之中。既可使用已有的枚舉項,也能夠將本身的枚舉項添加到這兩個枚舉的定義之中。你可使用數學表達式微調SYSINIT的執行順序。如下的例子示例了一個須要恰好要在內核參數調整的SYSINIT以前執行的SYSINIT。
static void
mptable_register(void *dummy __unused)
{
apic_register_enumerator(&mptable_enumerator);
}
SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST,
mptable_register, NULL);
宏SYSUNINIT()的行爲與SYSINIT()的至關,只是它將數據項填加至SYSINIT的析構數據集合。
#include <sys/kernel.h>
void foo_cleanup(void *unused)
{
foo_kill();
}
SYSUNINIT(foobar, SI_SUB_FOO, SI_ORDER_FOO, foo_cleanup, NULL);
struct foo_stack foo_stack = {
FOO_STACK_VOODOO;
}
void foo_flush(void *vdata)
{
}
SYSUNINIT(barfoo, SI_SUB_FOO, SI_ORDER_FOO, foo_flush, &foo_stack);