__init
is a Linux kernel macro, it is somewhat similar to the normal gcc __attribute__(constructor)
, with the additional feature that it's also interpreted as a hint that the code can be freed once it has run (modules only, platform dependent). In a "normal" gcc/glibc C program, libc takes care of calling any init (and fini) functions, in the kernel you need to use module_init()
(and module_exit()
) explicitly.
From include/linux/init.h
:
/* These macros are used to mark some functions or
* initialized data (doesn't apply to uninitialized data)
* as `initialization' functions. The kernel can take this
* as hint that the function is used only during the initialization
* phase and free up used memory resources after
[...]
#define __init __section(.init.text) __cold notrace
There are similar macros to mark exit functions, and data. These are the compiler/linker instructions:
__section()
to place the code in the .init.text
section (to jettison)
__cold
instructs the compiler (via __attribute__()
to not optimise calling path since the function is rarely called (once!)
notrace
to prevent possible problems with ftrace
A simple way to re-invoke module initialisation is to unload and reload the module (sometimes useful for getting a device unwedged).
If there are parts of the initialisation routines which might be useful at runtime, these may be placed in functions not marked __init
, and invoked from the real initialisation
function. You may mark multiple functions with __init
, exactly one must also be used in module_init()
, and such function should not be called by your code otherwise. The main point is that the module initialisation code is as much about setting up the kernel API as it is about initialising any hardware or non-hardware driver capabilities (which I'm guessing is the problem you have).
See also: