What?
Linux内核的整体结构非常庞大,其包含的组件也非常多,如何使用需要的组件呢?① 把所有组件都编译进内核文件,即:zlmage或bzlmage,但这样会导致两个问题:一是生成的内核文件过大;二是如果要添加或删除某个组件,需要重新编译整个内核。
模块功能:
有没有一种机制能让内核文件(zlmage或bzlmage)本身并不包含某组件,而是在该组件需要被使用的时候,动态地添加正在运行的内核中?答:有一种机制可以实现,Linux提供了一种叫做“内核模块”的机制,就可以实现以上效果。
内核模块特点:
模块本身并不被编译进内核文件(zlmage或bzlmage)。
可以根据需求,在内核运行期间动态的安装或卸载。
程序结构:
Hello.c
#include
#include
static int hello_init(void)
{
printk(KERN_WARNING"Hello,world!\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_INFO"Goodbye,world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile
ifneq ($(KERNELRELEASE),)
obj-m :=Hello.o
else
KDIR :=/lib/modules/3.13.0-32-generic/build
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.c *.symvers
endif
显示结果:
main.c
#include
#include
//#include
MODULE_LICENSE("GPL"); //许可证申明
MODULE_AUTHOR("hello_worldmy"); //作者申明
MODULE_DESCRIPTION("Hello World Module"); //模块描述
MODULE_ALIAS("a simplest module"); //模块别名
extern int add(int a,int b);
static int hello_init(void)
{
printk("Hello World!\n");
add(1,2);
return 0;
}
static void hello_exit(void)
{
printk("<7> hello <0> exit\n");
}
module_init(hello_init);
module_exit(hello_exit);
add.c
int add(int a,int b)
{
return a + b;
}
Makefile
ifneq ($(KERNELRELEASE),)
obj-m :=MyModule.o
MyModule-objs :=main.o add.o
else
KDIR := /lib/modules/3.13.0-32-generic/build
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif
显示结果:
在Makefile文件中MyModule为模块名,必须与下面的MyModule-objs中的MyModule保持一致。
MyModule-objs后添加的是源代码文件:main.o add.o;如果在操作中,超过两个的文件只需向后一直添加即可,文件与文件之间以空格间隔。
在该内核模块开发中,内核模块由单个源文件构成或内核模块由多个源文件构成生成的模块是以 .ko结尾的文件。在该示例中,示例一的模块为Hello.ko;示例二的模块为MyModule.ko。
模块安装与卸载:
加载insmod (insmod hello.ko)
卸载 rmmod (rmmod hello)
查看 lsmod
加载 modprobe (modprobe hello)
Modprobe如同insmod,也是加载一个模块到内核。它的不同之处在于它会根据文件
来查看要加载的模块,看它是否还依赖于其他模块,如果是,modprobe会首先找到这些模块,把它们先加载到内核。
示例一:
示例二:
模块可选信息:
1、许可证申明:宏MODULE_LICENSE用来告知内核,该模块带有一个许可证,没有这样的说明,加载内核模块时内核会抱怨。有效的许可证有“GPL”、“GPLv2”、“GPL and additional rights”、“Dual BSD/GPL”、“Dual MPL/GPL”和“Proprietary”。
2、作者申明(可选)
MODULE_AUTHOR(“Sir”);
3、模块描述(可选)
MODULE_DESCRIPTION(“Hello World Module”);
4、模块版本(可选)
MODULE_VERSION(“V1.0”);
5、模块别名(可选)
MODULE_ALIAS(“a simple module”);