版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原文出处,谢谢
原文出处: http://libiao.appspot.com/2009/07/first_lkm_intro.html
LKM: Loadable Kernel Module,也叫KLD (Dynamic Kernel Linker)就是编写可动态加载和卸载的内核模块。使用kldload(8)加载内核模块,使用kldunload(8)卸载内核模块,使用kldstat(8)来显示查看已经加载的内核模块。调用kldload(8),必须要在内核上链接并且注册上,在FreeBSD的内核编程上,可以使用宏DECLARE_MODULE来进行链接和注册,
宏DECLARE_MODULE一共有4个参数
第一个参数是模块的名称,传入的是一个字符串,但是很奇怪的是,好像这个字符串不需要加引号
第二个参数是最重要的一个参数,其为数据结构struct moduledata(即moduledata_t类型结构),在该结构中保存该模块的官方名称,事件处理函数以及一些额外的数据
如:
static moduledata_t hello_mod = {
"hello",
load,
NULL
};
其中load是一个事件处理函数,其处理了如下的事件
typedef enum modeventtype {
MOD_LOAD,/* 当模块以及被加载后触发*/
MOD_UNLOAD,/*当模块被卸载的时候触发*/
MOD_SHUTDOWN,/*当在SHUTDOWN的时候触发*/
MOD_QUIESCE/*当模块quiesce时候触发*/
}
第三个参数是该模块的类型,可选值可以参考enum sysinit_sub_id(在sys/kernel.h),一般情况下是使用SI_SUB_DRIVERS
第四个参数是KLD初始化的顺序,可以参考enum sysinit_elem_order(在sys/kernel.h)中的值,一般情况下是使用SI_ORDER_MIDDLE
实例:
DECLARE_MODULE(hello,hello_mod,SI_SUB_DRIVERS,SI_ORDER_MIDDLE);
下面是整个代码
#include #include #include #include static int load(struct module* module,int cmd,void* arg) { int error = 0; switch(cmd) { case MOD_LOAD: uprintf("Hello world\n"); break; case MOD_UNLOAD: uprintf("Good-Bye, cruel world!\n"); break; default: error = EOPNOTSUPP; break; } return error; } static moduledata_t hello_mod = { "hello", load, NULL }; DECLARE_MODULE(hello,hello_mod,SI_SUB_DRIVERS,SI_ORDER_MIDDLE);
对于整个内核模块的Makefile文件如下:
KMOD= hello
SRCS= hello.c
.include <bsd.kmod.mk>
最后是对该模块进行编译,执行的结果
sunrise# make Warning: Object directory not changed from original /usr/home/kingoal/tmp/kernel cc -O2 -fno-strict-aliasing -pipe -D_KERNEL -DKLD_MODULE -std=c99 -nostdinc -I. -I@ -I@/contrib/altq -finline-limit=8000 --param inline-unit-growth=100 --param large-function-growth=1000 -fno-common -mno-align-long-strings -mpreferred-stack-boundary=2 -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -ffreestanding -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual -Wundef -Wno-pointer-sign -fformat-extensions -c hello.c ld -d -warn-common -r -d -o hello.kld hello.o :> export_syms awk -f /sys/conf/kmod_syms.awk hello.kld export_syms | xargs -J% objcopy % hello.kld ld -Bshareable -d -warn-common -o hello.ko hello.kld objcopy --strip-debug hello.ko sunrise# kldstat Id Refs Address Size Name 1 3 0xc0400000 9fab28 kernel 2 1 0xc0dfb000 6a45c acpi.ko sunrise# kldload ./hello.ko Hello world sunrise# kldstat Id Refs Address Size Name 1 4 0xc0400000 9fab28 kernel 2 1 0xc0dfb000 6a45c acpi.ko 3 1 0xc2afb000 2000 hello.ko sunrise# kldunload hello.ko Good-Bye, cruel world! sunrise# kldstat Id Refs Address Size Name 1 3 0xc0400000 9fab28 kernel 2 1 0xc0dfb000 6a45c acpi.ko sunrise#
永久链接: http://libiao.appspot.com/2009/07/first_lkm_intro.html