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);