Sysinit is a common framework for calling sorting and executing mechanisms separately. FreeBSD is currently using it for dynamic initialization of the kernel. Sysinit makes the kernel or modules of the FreeBSD can be restructured, added, deleted, and replaced when the kernel or module dynamically loads the link, so that the kernel and module do not have to modify a static ordered initialization schedule or even recompile the kernel when loading. This system also makes the kernel modules (now called KLD can be compiled, linked, and loaded when booting the system, even when the system is running). These operations are done through the kernel Linker (kernel linker) and the linker collection (linker set). The linker collection (Linker set) is a link method. This method collects statically declared data from the entire program source file into a contiguous addressable data unit. Sysinit relies on the linker to obtain static data that is all over the entire program's source code and to form a block of data that is adjacent to each other. This link method is called the linker collection (linker set). Sysinit uses two linker collections to maintain two sets of data, including the invocation order of each data entry, a function, and a data pointer that will be submitted to the function.
Sysinit the function by two types of priority identification for execution. The identification of the first class priority is the identification of the subsystem, and the global order of the functions of the Sysinit subsystem is given, which is defined in the enumeration sysinit_sub_id. The second type of priority identifies the order of elements in the subsystem, defined in the enumeration Sysinit_elem_order in. There are two kinds of times when you need to use Sysinit: System startup or kernel module loading, system destructor or kernel module uninstall. Kernel subsystems typically use SYSINIT definitions to initialize data structures at system startup. For example, the process scheduling subsystem uses a SYSINIT definition to initialize the running queue data structure. Device drivers should avoid direct use of sysinit (), the physical real device on the bus structure should use the driver_module () called function to detect the presence of the device, if it exists, then the initialization of the device. During this system, something specific to the device is done, and then the Sysinit () itself is invoked. For virtual devices that are part of a non-bus structure, you should use Dev_module () instead.
Using Sysinit
Interface
Header file
<sys kernel.h>
Macro
Sysinit (Uniquifier, subsystem, order, Func, ident)
Sysuninit (Uniquifier, subsystem, order, Func, ident)
Start
The macro Sysinit () creates a Sysinit data item in the Sysinit startup data collection to Sysinit sort and execute functions in the system startup or module load. Sysinit () has a parameter uniquifier,sysinit that identifies the data item, followed by the subsystem sequence number, the subsystem element order number, the function to call, and the data passed to the function. All functions must have a constant pointer parameter.
Examples of Sysinit ()
#include
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);
Note that Si_sub_foo and Si_order_foo should be in the enumerated sysinit_sub_id and Sysinit_elem_order mentioned above respectively. You can either use an existing enumeration entry or add your own enumeration entries to the definitions of these two enumerations. You can use mathematical expressions to fine-tune the order in which Sysinit are executed. The following example illustrates a sysinit that needs to be executed just before the sysinit of the kernel parameter adjustment.
An example of adjusting the order of 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);
destructor
The behavior of the macro Sysuninit () is the same as the Sysinit (), except that it fills the data item to the Sysinit collection of destructor data.
Examples of Sysuninit ()
#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);