L哪些是内核模块
(1)内核模块是具有独立功能的程序,它可以被单独的编译,而且不能独立的运行,他必须联接到内核作为内核的一部份在内核空间中运行。
(2)模块编程与内核版本密切相关,因为不同的内核版本中个别函数的函数名会有变化。因而模块编程也可叫做内核的编程。
(3)特性:模块本身不被编译进内核映像,进而控制了内核的大小;模块一旦被加载就和内核中的其他部份完全一样。
用户层编程与内核模块编程的区别:
编撰内核模块
testm.c文件:
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("weipeng jing");

MODULE_DESCRIPTION("Hello World Module");
MODULE_ALIAS("a simplest module");
static int __init hello_init()
{
printk(KERN_EMERG"Hello World!n");
return 0;
}
static void __exit hello_exit()
{
printk("hello exitn");
printk(KERN_EMERG"good bye!n");
}
module_init(hello_init);
module_exit(hello_exit);
#include
#include
编撰内模块程序的必须的头文件
因为内核编程与用户编程所用的库函数不同,所以头文件也不同。
内核头文件的位置:/usr/src/linux2.6.29/include/
用户头文件的位置:/usr/include/
加载函数staticinthello_init(void);//不加 void 在调试时会出现报案
卸载函数staticvoidhello_exit(void);// 不加 void 会出现报案 , 若改为 static int 也会报错 , 由于出口函数是不能返会值的
在模块编程中必需要有前面这两个函数;
注册函数和卸载函数还有一种写法二者的区别与联系:
1> 模块加载函数
staticint_initinit_fun(void)
printk(“helloworld/n”);
return0;
2> 卸载函数 无返回值
static void __exit exit(void){
printk(“byebye!/n”);
通过比较我们可以发觉第二个函数区别在于一个有_init
和_exit前缀,_init与_exit都是Linux内核的一个宏定义,使系统在初始化完成后释放该函数,并释放其所占的显存。因而它的优点是显而易见的,所以通常都建议使用第二种写法。
(1)在Linux内核中,所有标识_init的函数在联接时都置于.init.text这个区段内,再者。所有的_init函数在区段.initcall.init中还保存了一份函数的表针linux rar,在初始化时内核会通过这种表针调用那些_init函数,并在初始化完成后释放_init区段。
(2)和_init一样linux内核编程,_exit也可以使对应的函数在运行完成后手动的回收显存。
printk()函数
printk是内核态的信息
复印函数,功能和标准的printf类似,而且printk有信息复印级别。
intprintk(constchar*fmt,…)
消息的复印级别:
fmt–消息级别:
#defineKERN_EMERG“”/紧急风波消息,系统崩溃之前的提示,表示系统不可以用。
#defineKERN_ALERT””/报告消息,表示必须立刻采取举措。
#defineKERN_CRIT””/临界条件linux内核编程,一般涉及严重的硬件或软件操作失败。
#defineKERN_ERR””/错误条件,驱动程序常用KERN_ERR来报告错误。
#defineKERN_WARNING””/警告条件,对可能出现的问题情况进行警告。
#defineKERN_NOTICE””/正常但又重要的条件,用于提醒。经常用于安全相关的信息。
#defineKERN_INFO””/提示信息linux查看硬件信息,如驱动程序启动时,复印硬件信息。
#defineKERN_DEBUG””/调试级别信息。
不同的级别用不同的字符串表示,数字越小级别越高。
在内核态使用printk()而在用户态使用printf()是由于,printk()函数是直接的使用了向终端写函数tty_write(),而printf()函数时调用write()系统调用函数向标准输出设备写,所以在用户态不能直接的使用printk()函数,而在内核态因为它已是特权级,所以无需系统调用来
改变特权级,因此能直接使用printk()函数。printk()是内核态的输出,在终端是看不见的,可以使用cat/var/log/messages,或则是dmesg命令来查看输出信息。
加载模块与卸载模块
modules_init(hello_init)告诉内核你编撰的模块程序从那里开始执行。
modules_exit(hello_exit)告诉内核你编撰的模块程序从那里离开。
参数就是卸载函数与注册函数的函数名
许可权限,
MOUDLES_LICENSE(“DUALBSD/GPL);
在linux2.6中可接受的LICENSE包括“GPL”,“GPLV2”,“GPLandadditionalrights”,“DualMPL/GPL”,“Proprietary”。