内核模块是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