开发一个简单的内核程序

​前面文章我们介绍了如何编译一个内核,也了解到了编译内核并不难。今天这篇文章我们将介绍一下如何开发一个简单的内核程序。

实例源程序

用于态的程序类似,Linux的内核程序也是有规范的。用户态的程序必须以main函数作为入口,而内核程序则必须包含一个加载函数和一个卸载函数。这是因为内核程序是一个内核模块,加载函数是模块加载的时候执行,而卸载函数则是在模块卸载的时候执行。

模块的加载函数和卸载函数需要通过内核API进行注册,也就是module_init和module_exit函数,也就是19行,20行的内容。

头文件自然不必多说,这个与用户态程序类似,必须要包含必要的头文件(2-4行)。另外一个必要的是第6行的License字段,这个也是必须的。

这里实现的功能是在模块加载和卸载的时候打印“Hello World”字符串。打印字符串使用的是printk函数,该函数与用户态的printf函数类似。需要注意的是字符串并不会打印到终端,而是打印到系统日志里面,可以通过dmesg命令查看。

Makefile文件

内核程序需要一个配套的Makefile文件,文件名称必须为Makefile,第一个字母大写。该文件的格式如下所示。其中第一行定义了模块的名称,然后接下来分别是当前路径,内核版本和内核源代码路径。

在这个Makefile文件中有两个目标,一个是编译目标all,用于生成二进制文件;另外一个则是清理目标,用于清理临时文件。

编译与运行

程序的编译非常简单,在当前目录执行make命令即可:

make

执行完命令后, 可以看到目录下出现了很多文件,其中hello.ko是生成的二进制文件,类似Windows下的exe文件。

如何执行该二进制文件呢?很简单,执行如下命令就行:

insmod hello.ko

执行成功后,通过lsmod可以看到该内核模块被加载了。

此时通过dmesg命令可以看到打印的内容。至此,我们完成了一个内核程序的开发,编译和运行。是不是很简单!

附录

最后,我们附上上述程序的源代码。下面是程序的源代码。

//必要的头文件

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/init.h>

//模块许可证声明(必须)

MODULE_LICENSE("Dual BSD/GPL");

//模块加载函数(必须)

static int hello_init(void)

{

printk(KERN_ALERT "Hello World\n");

return 0;

}

//模块卸载函数(必须)

static void hello_exit(void)

{

printk(KERN_ALERT "Hello World\n");

}

//模块的注册

module_init(hello_init);

module_exit(hello_exit);

//声明模块的作者(可选)

MODULE_AUTHOR("SunnyZhang");

//声明模块的描述(可选)

MODULE_DESCRIPTION("This is an example!/n");

//声明模块的别名(可选)

MODULE_ALIAS("A simplest example");

下面是Makefile文件的源代码。

obj-m += hello.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

(0)

相关推荐