AUTHOR: Joseph Yang (楊紅剛) <[email protected]>
CONTENT: LKM -- load and unload process
NOTE: linux-3.0
LAST MODIFIED:09-27-2011
-----------------------------------------------------------------------------------------------------------
Distributed and Embedded System Lab (分布式嵌入式系統實驗室,蘭州大學)
===============================================================
LKM -- load and unload process
------------------------------------
contents:
1. Brief introduction about LKM.
2. Short introduction of ELF
3. Module loading & Module unloading
4. Conclusion
5. REF
---------------------------------
1. Brief introduction about LKM.
1.1
The Linux kernel is what's known as a monolithic kernel, which means that the majority of the
operating system functionality is called the kernel and runs in a privileged mode. This differs from
a micro-kernel, which runs only basic functionality as the kernel (inter-process communication [IPC],
scheduling, basic input/output [I/O], memory management) and pushes other functionality outside
the privileged space (drivers, network stack, file systems).
Linux can be dynamically altered at run time through the use of Linux kernel modules (LKMs).
Dynamically alterable means that you can load new functionality into the kernel, unload functionality
from the kernel, and even add new LKMs that use other LKMs.
1.2 A source view of LKM
#include <linux/module.h>
#include <linux/init.h>
static int __init lkm_init(void)
{
printk("This will be called when module is loaded\n");
return 0;
}
static void __exit lkm_exit(void)
{
printk(" This will be called when module is deleted\n");
}
MODULE_LICENSE("GPL");
module_init(lkm_init);
module_exit(lkm_exit);
2. Short introduction of ELF (abbreviation of Executable and Linkable Format)
2.1 Intuitive view of ELF
$ objdump -h hello.ko // show section headers
.text // instructions
.init.text // init instructions
.exit.text // exit instructions
.rodata.str1.4 // read-only strings
.modinfo // module macro text // modinfo *.ko
.data // Initialized data
.bss // Uninitialized data
.gnu.linkonce.this_module // module's name, init & exit function's addresses
// vim *.mod.c
2.2 tools which can be helpful
objdump -h hello.ko
readelf -p 17 hello.ko // read the contents of specified section
readelf -s hello.ko // can read content of '.symtab' section
readelf -S hello.ko // read section headers
readelf -e hello.ko // ELF header and section headers
2.3 Link view of ELF
----------
ELF header
----------
Program header table
----------
section 1
--------
section 2
...
-------
section header table
-----------
What every part used for ??
Ans: readelf -e hello.ko // ELF header and section headers
REF: More information about the ELF, you can refer 'TIS ELF Specification V 1.2'
3. Module loading & Module unloading
3.1
The process of module loading begins in user space with insmod (insert module).
The insmod command defines the module to load and invokes the init_module user-space
system call to begin the loading process. The init_module function works through the system
call layer and into the kernel to a kernel function called sys_init_module.
Similarly, the rmmod command results in a system call for delete_module, which eventually
finds its way into the kernel with a call to sys_delete_module to remove the module from the kernel.
REF: System call : http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN976
3.2 Loading process
sys_init_module():
1> permission check // capable(),modules_disabled
2> Allocate, load module and create corresponding control files in sysfs //load_module() ***
3> Call module notify list with state change (MODULE_STATE_COMING) //blocking_notifier_call_chain
4> Set the property for 'core' and 'init' section: // set_section_ro_nx
Set RO for module text and RO-data and Set NX permissions for module data.
5> Call the module's init function.(mod->init()) // do_one_initcall ++ Module is alive
6> mod->state = MODULE_STATE_LIVE
7> wake up all tasks waiting for the initialization of this module in queue 'module_wq'
8> Call module notify list with state change(MODULE_STATE_LIVE)
9> Unset the RO and NX property for 'init' section. //unset_module_init_ro_nx
10> Free the memory related to 'module init'. //module_free
Detail of function load_module():
1> Allocate temporary memory for the module, copy the module image from userspace,
and do module checking. // copy_and_check
2> layout module allocate memory and copy corresponding sections to the final position.
// layout_and_allocate
3> Init the unload section of the module. //module_unload_init <two lists>
4> Find optional sections and set corresponding items in mod //find_module_sections
5> check_module_license_and_versions(mod)
6> //setup_modinfo
7> Fix up syms, so that st_value is a pointer to location. //simplify_symbols
8> Aplly relocations, copy relocated percpu area over. //apply_relocations, post_relocation
9> Flush the instruction cache // flush_module_icache
10> Copy the arguments from userspace to kernel space. //strndup_user
11> Set the module state to MODULE_STATE_COMING
12> Verify there is no duplicate symbols. //verify_export_symbols
13> Add the module to the global moudle list -- modules //list_add_rcu
14> //parse_args
15> create corresponding control files in sysfs //mod_sysfs_setup
16> //kfree, free_copy
Done!!!
3.3 Unloading process
sys_delete_module():
1> permission check // capable(),modules_disabled
2> Copy module name from userspace //strncpy_from_user
3> Find the pointer to the module which should be unloaded // find_module
4> Make sure that no other modules are depend on this module //list_empty
5> Verify the module state, make sure the module is in MODULE_STATE_LIVE state
6> //try_stop_module
7> Wait for the module's reference couter becoming 0 //wait_for_zero_refcount
8> Call the module's exit function // mod->exit()
9> Call module notify list with state change(MODULE_STATE_GOING)
//blocking_notifier_call_chain
10> Synchronize all asynchronous function calls //async_synchronize_full
11> //free_module ****
Detail of free_module():
1> Delete the corresponding control files under /sys // mod_sysfs_teardown
2> // module_arch_cleanup
3>
4> Unset the RO and NX property for 'init' section. //unset_module_init_ro_nx
5> Free the memory related to 'module init'. //module_free
6> kfree(mod->args)
7> Free the percpu variables //percpu_modfree
8>
Unset the RO and NX property for 'core' section. //unset_module_init_ro_nx
Free the memory related to 'module core'. //module_free
OK!!!
4. Conclusion
This is a brief introduction of module load and unload. More detail information you can read
the source code(kernel/module.c). Before reading the source code you'd better read the
ELF format then you can get a better understanding of "why".
5. REF:
http://www.ibm.com/developerworks/linux/library/l-lkm/?S_TACT=105AGX52&S_CMP=cn-a-l
More information about the ELF, you can refer 'TIS ELF Specification V 1.2'
System call : http://tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN976
Thank you!