编写简单的内核模块——Linux操作系统原理与应用(陈莉君第2版13页)

1.什么是内核模块

这对于初学者无非是个非常难以理解的概念。内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个单内核(monolithic kernel)。单内核的最大优点是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。
模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。
总之,模块是一个为内核(从某种意义上来说,内核也是一个模块)或其他内核模块提供使用功能的代码块。

2.编写一个简单的内核模块

2.1程序清单

#include 
#include 
#include 

static int lkp_init(void)
{
printk("<1>Hello,WOrld! from the kernel space...\n");
return 0;
}

static void lkp_cleanup(void)
{
printk("<1>Goodbye,World! leaving kernel space...\n");
}

module_init(lkp_init);
module_exit(lkp_cleanup);
MODULE_LICENSE("GPL");


2.2详细说明
2.3编译模块

#Makefile
obj-m := hellomod.o
CURRENT_PATH := $(shell pwd)
LINUX_KERNEL := $(shell uname -r)
LINUX_KERNEL_PATH := /usr/src/kernels/$(LINUX_KERNEL)

all:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
        make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

用make命令运行Makefile,结果如下:

2.4运行代码

编译好模块之后,就可以把新的模块插入到内核中,具体命令
insmod hellomod.ko
注意:这句命令需要在超级用户模式下运行
此时可以使用 lsmod 命令,查看模块是否正确插入到内核
另外,在源代码清单中,我们使用了 printk()来进行内核模块的输出,printk()函数默认打印系统文件 /var/log/message的内容,要打印日志文件的最后10行,采用以下命令
tail /var/log/meaasge

可以看到,最后一行是printk()函数的内容

移除内核模块的命令为
rmmod hellomod
利用上文所提到的命令查看日志文件,得到退出内核模块所显示的信息


3.出错及解决方案

在此次编译过程中,主要遇到了以下几个问题

问题一

按照课本上的Makefile编写,运行出错,错误信息如图所示,课本原有Makefile代码中有这样一行
LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL)
此处是Linux内核源代码的绝对路径,不同版本号,路径有所不同,所以我们对代码进行修正,只需要把自己的内核源码绝对路径写进去即可
LINUX_KERNEL_PATH := /usr/src/kernels/$(LINUX_KERNEL)
这样进行编译就不会出错

问题二

内核模块无法正确插入
检查Makefile文件


注意  Makefile的格式要求非常严格
obj-m := hellomod.o 这句 obj和-m之间没有空格,并且:和=之间也没有空格
修改后即可完成整个流程操作

你可能感兴趣的:(Linux操作系统原理与应用)