# Toaru Kernel Modules とあるOS supports loadable kernel modules since 0.6. Kernel modules are relocatable ELF object files that can be included during the boot process or loaded later, and allow for kernel functionality to be extended without adding complexity to the base kernel. Currently, kernel modules are used to support some device drivers (serial, ATA), virtual devices (DOS partitions, procfs, null/zero/random), file systems (ext2), and a kernel debug shell. ## Why Write a Module? If you are implementing a hardware driver, want to supply optional extensions, or want to write additional debug shell commands, you should write a module. ## Actually Writing a Module Modules are single C source files in the `modules/` directory. Future revisions to the build system will support modules made up of multiple C sources. Modules have access to all exported kernel functions and symbols and use the same header include path as other parts of the kernel. ### Hello World Module The following sample creates a simple "hello world" module. It prints "hello world" to the kernel debug log when it is loaded. ```c #include #include static int init(void) { debug_print(NOTICE, "hello world"); return 0; } static int fini(void) { return 0; } MODULE_DEF(hello, init, fini); ``` From this example, we can see that a simple module conists of initialization function (`init`), a finish function (`fini`), and a module definition. The details of the implementation of `MODULE_DEF` are unimportant; its first argument is the name of the module, which will be used to identify it to other parts of the module system; the name of the initializer function, which will be run when loaded; and the name of the finishing function, which is run at unload. To obtain the `MODULE_DEF` macro, the `` header must be included. We also include `` to get `debug_print`. ### Extended the Debug Shell We can also use modules to extend other modules. The following example will create a module that adds a new debug shell command: `hello`. ```c #include #include DEFINE_SHELL_FUNCTION(hello, "Print 'hello world'") { fs_printf(tty, "hello world\n"); return 0; } static int init(void) { BIND_SHELL_FUNCTION(hello); return 0; } static int fini(void) { return 0; } MODULE_DEF(hello, init, fini); MODULE_DEPENDS(debugshell); ``` The `MODULE_DEPENDS` macro specifies a single dependency of the module - in this case, the `debugshell` module. `DEBUG_SHELL_FUNCTION` and `BIND_SHELL_FUNCTION` macros are provided by `` and allow us to define additional shell functions and bind them. Both macros take the name of the function as their first argument, while the former also takes a description to be listed in the output of the `help` command. Debug shell functions take the following arguments: `fs_node_t * tty, int argc, char * argv[]`. They should return an `int`, with `0` indicating success. ## Other Kinds of Modules Modules can also be used to provide virtual devices, including drivers for block devices or character devices, file systems, and more. For examples of these kinds of modules, please refer to the sources in the `modules/` directory.