Linux属于单内核,为了弥补单内核扩展性与维护性差的缺点,Linux引入动态可加载内核模块,模块可以在系统运行期间加载到内核或从内核卸载。模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。

下面是一个简单的例子:
(1)模块hello.c文件

#include <linux/init.h>
//指定初始化和清理函数
#include <linux/module.h>
//包含了大量加载模块需要的函数和符号的定义。
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("WFJ");
//声明模块的许可证,适用GNU通用公共许可的任何版本
static int hello_init (void)
{
    printk(KERN_ALERT"Hello module init/n");
    return 0;
}
//初始化函数应当声明为静态的
static void hello_exit (void)
{
    printk(KERN_ALERT"Hello module exit/n");
}
//清理函数,它注销接口,在模块被去除之前返回所有资源给系统。
module_init(hello_init);
//这个宏定义增加了特别的段到模块目标代码中,表明在哪里找到模块的初始化函数
//没有这个定义,初始化函数不会被调用
module_exit(hello_exit);

一个linux内核模块需包含模块初始化和模块卸载函数,模块初始化在insmod的时候运行,模块卸载函数在rmmod的时候运行,初始化和卸载函数必须在宏module_init和module_exit使用前定义,否则会出现编译错误。

(2)Makefile文件

CONFIG_MODULE_SIG=n

obj-m := hello.o

KERNELBUILD :=/usr/src/linux-source-3.13.0

default:

    make -C $(KERNELBUILD) M=$(shell pwd) modules

clean:

    rm -rf *.o  *.ko *.mod.c .*.cmd .tmp_versions *.order *.symvers

(3)编译模块
make命令编译,编译完会产生若干新的文件:hello.ko、hello.mod.c、hello.mod.o、hello.o、modules.order、Module.symvers。其中hello.ko即为所需。
(4)插入模块

sudo insmod hello.ko

(5)查看模块

lsmod

lsmod 其实就是list modules的缩写,即列出所有模块。
(6)查看hello.c文件的输出内容
在端口是不会打印出hello.c文件的输出内容,但是可以使用dmesg命令来查看。

dmesg > hello.txt

将dmesg的输出内容保存在hello.txt文件中,若在Makefile文件中没有CONFIG_MODULE_SIG=n这条语句,那么hello.txt文件中将会显示:
[ 9753.845869] hello: module verification failed: signature and/or required key missing - tainting kernel
即:模块验证失败。若有这条语句,则hello.txt文件中将会显示:

[ 9753.846136] Hello module init/n
[12601.703040] Hello module exit/n

即:输出了hello.c文件的输出内容。
(7)卸载模块

sudo rmmod hello.ko

参考文章:
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=9112803&id=3155470

http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN44