1.先看程序的头文件(参考hello.c)
# include <linux/module.h> /* Need by all modules */
# include <linux/kernel.h> /* Need for HERN_INFO */
# include <linux/init.h> /* Need for the macros */
# include <linux/kernel.h> /* Need for HERN_INFO */
# include <linux/init.h> /* Need for the macros */
这三个头文件是编写内核模块程序必须的。
- 由于内核编程和用户编程所用的库函数不一样,所以他的头文件也和我们在用户层编写程序时所用的头文件不 一样。
- Linux中头文件存放位置:
b.用户层头文件位置:/usr/include
2.内核模块的(加/卸载)函数:
- 加载函数:
{
printk(KERN_INFO "Hello world\n");
/*
A non 0 return means init
*/
return 0;
}
- 卸载函数(无返回值):
{
printk(KERN_INFO "Goodbye world\n");
}
3.对比hello.c中的(加/卸载)函数
# include <linux/init.h> /* Need for the macros */
static int __init hello_init(void)
{
printk(KERN_INFO "Hello world\n");
/*
A non 0 return means init
*/
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye world\n");
}
{
printk(KERN_INFO "Hello world\n");
/*
A non 0 return means init
*/
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "Goodbye world\n");
}
注解:通过比较我们发现第二种函数在函数名称前加了__init和__exit前缀(
init 和 exit 前面都是两个下划线)。
- 那么第二种方法比第一种有什么好处呢?
_init 和 __exit 是 Linux 内核的一个宏定义,使系统在初始化完成后释放该函数,并释放其所占内存。因此它的优点是显而易见的。所以建议大家啊在编写入口函数和出口函数时采用第二中方法。
(1) 在 linux 内核中,所有标示为 __init 的函数在连接的时候都放在 .init.text 这个区段内,此外,所有的 __init 函数在区段 .initcall.init 中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些 __init 函数,并在初始化完成后释放 init 区段(包括 .init.text,.initcall.init等)。
(2) 和 __init 一样, __exit 也可以使对应函数在运行完成后自动回收内存。