内核模块是Linux内核向外部提供的一个插口,其全程为动态可加载内核模块(LVM,Loadable Kernel Module),简称模块
内核模块是具有独立功能的程序,可以被单独编译,但不能独立运行
它在运行时被链接到内核作为内核的一部分在内核空间,这和我们平时在用户空间的进程不同
内核模块通常由一组函数和数据结构构成
Linux是一个单内核操作系统
它有着单内核的优点效率高,因为所有内容都集成在一起
同样,缺点也是显而易见的,可扩展性和可维护性相对较差,模块机制正是为了弥补这一缺陷
模块作为内核功能的一个扩展,是为了在保持内核体积较小的情况下,增强其功能
内核只需要完成必要的功能即可,其他的功能都可以通过模块进行增强,类似于Vim的插件机制
内核模块用来实现一种文件系统,一个驱动程序和其他内核上层的功能
- /*hello_world.c*/
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
-
- MODULE_LICENSE("GPL");
-
- static int __init hello_init(void)
- {
- printk(KERN_ALERT "Hllo,kernel world\n");
- return 0;
- }
-
- static void __exit hello_exit(void)
- {
- printk(KERN_ALERT "goodbye,kernel\n");
- }
-
- module_init(hello_init);
- module_exit(hello_exit);
-
- MODULE_AUTHOR("MwumLi");
- MODULE_DESCRIPTION("Hello World's kernel version!\n");
一些说明:
对于一般的C程序,我们只需要gcc就可以了,然后直接运行
但是内核模块程序,我们必须使用内核中makefile文件,里面包含了内核库的位置
因此,我们需要编写makefile文件来实现内核模块的编译
- # this is a Makefile
- obj-m += hello_world.o
- #generate the path
- CURRENT_PATH:=$(shell pwd)
- #the current kernel version number
- LINUX_KERNEL:=$(shell uname -r)
- #the absolute path
- LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
- #complie object
- all:
- make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
- #clean
- clean:
- make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
然后,在命令行下:
- $ sudo make
-
这样就可以成功编译(报错的话,根据错误信息debug)
- $ sudo insmod hello_world.ko
-
- $ sudo lsmod | head
-
你会发现hello_word在第一行,okay,加载成功
- $ sudo rmmod hello_world
-
- $ sudo modinfo hello_world.ko