首页 > 代码库 > linux中添加内核模块

linux中添加内核模块

1.  内核模块简介

Linux 内核的 整 体结构 非 常 庞 大 ,其 包 含 的 组 件也 非 常多 , 如 何使用 需 要 的 组 件 呢?

  方 法 一 : 把 所有的 组 件都 编译 进 内核 文 件, 即 :zImage 或bzImage , 但 这样会 导 致 两 个 问 题 : 一是 生 成的 内核 文 件 过大 ;二 是 如果 要 添 加 或 删 除某 个 组 件, 需 要重 新 编译 整 个内核

方法二:使用内核模块, 内核 文 件(zImage 或bzImage) 本 身 并不 包 含 某 组 件 , 而 是 在该 组 件 需要 被 使用的 时 候 ,以模块的方式动 态地 添 加 到 正 在 运行 的内核中 


2. 内核 模块 具 有 如下特 点 :
? 模块 本 身 并 不 被编译 进 内核 文 件( zImage 或者bzImage )
? 可以 根 据 需 求 , 在内核 运行 期 间 动 态 的安 装 或 卸 载 


3. 范 例(hello world)

#include <linux/init.h>
#include <linux/module.h>
static int hello_init(void)
{
printk(KERN_WARNING"Hello, world !\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_INFO "Goodbye, world\n");
}
module_init(hello_init);
module_exit(hello_exit);

4. 程序结构说明

模块加载函数(必需):安 装 模块 时 被系统 自 动 调 用的 函 数 , 通 过module_init 宏 来指定,以上例子,指定的加载的函数就是hello_init

模块卸载函数(必须):卸 载 模块 时 被系统 自 动 调 用的 函 数 , 通 过module_exit 宏 来 指定 ,以上例子,指定的加载的函数就是hello_exit


5.pritk函数说明

printk函数和printf的函数实现的功能是一样的,只不过一个运行在内核态,一个运行在用户态。

用printk函数打印时候,内核会根据日志级别,可能把消息打印到当前的控制台上, 这个控制台通常是一个字符模式的终端、一个串口打印机或是一个并口打印机。这些消息正常输出的前提是:日志输出级别小于控制台日志级别(在内核中数字越小优先级越高)。如果没有指定打印级别,默认的基本是<4>,即是KERN_WARNING级别,其定制可以再/kernelprintk.c中找到。


日志级别一共有8个级别,printk的日志级别定义如下(在include/linux/kernel.h中):

#define KERN_EMERG      0

#define KERN_ALERT      1
#define KERN_CRIT       2
#define KERN_ERR        3
#define KERN_WARNING    4
#define KERN_NOTICE     5
#define KERN_INFO       6
#define KERN_DEBUG      7

通过读写/proc/sys/kernel/printk文件可读取和修改控制台的日志级别

#cat /proc/sys/kernel/printk

44 1 7

上面显示的4个数据分别对应控制台日志级别、默认的消息日志级别、最低的控制台日志级别和默认的控制台日志级别

可以修改上面的数据修改控制台的打印级别

备注:ubuntu 图形化界面是无法打印到控制台的, printk打印的是控制台,也就是/dev/console,而图形界面中的终端,其实是把stdin,stdout,stderr三个文件重定向了一下。所以printk是无法再图形界面中的终端中显示的,当然可以再/var/log/syslog或者用dmesg查看。


6.  模块makefile编写,makefile名字必须命名为Makefile,否则编译通过不了,下面这个makefile会被编译两次,第一次KERNELRELEASE为空,去运行

KDIR下面的makefile,接着会重新调用自己的Makefile,编译成功,产生hello.o,hello.ko两个文件

ifneq ($(KERNELRELEASE),)

obj-m := hello.o//根据自己的模块修改

else

KDIR := /lib/modules/2.6.32-21-generic/build//根据自己lib/modules/下面自己内核版本库填写
all:
        make -C $(KDIR) M=$(PWD) modules
clean:
        rm -f *.ko *.o *.mod.o *.mod.c *.symvers

endif

7. 加载 模块insmod 

insmod hello.ko

可以通过lsmod  | grep hello查看自己刚刚加载的内核模块


8. 卸载模块rmmod

rmmod hello





linux中添加内核模块