#ifneq($(KERNELRELEASE),)
obj-m := hello.o
#else
KERNELDIR := /usr/src/linux/
modules:
$(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) $@
install:
insmod hello.ko
uninstall:
rmmod hello.ko
clean:
rm -rf *.ko *.o *.mod.c *.symvers *.order
/* ===================================================================================
上述makefile开始执行的时候,为定KERNELDIR义,所以为空,#ifneq($(KERNELRELEASE),)不成立,执行
else分支,执行到$(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) $@ 的时候,make 离当前路径,到
KERNELDIR := /usr/src/linux/ kernel路径下读取相关的配置文件信息,之后回到当前目录下再次从
头执行makefile 文件,这个时候KERNELRELEASE 已经定义,不为空,那就执行obj-m := hello.o命令
生成我们的目标.KO文件.
===================================================================================*/
module example:
/*/* ===================================================================================
* =====================================================================================
*
* Filename: hello.c
*
* Description: dragon
*
* Version: 1.0
* Created: 2011年08月02日 03时02分35秒
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Company:
*
* =====================================================================================
*/
#include
#include
static char *param1 = "param1\n";
static int param2 = 2;
module_param(param1, charp, S_IRUGO);
module_param(param2, int, S_IRUGO);
MODULE_LICENSE("GPL"); /* 必不可少*/
/* 下面的信息是模块详细信息,作者自己根据喜好可增加,目的便于
使用该模块的用户能用诸如modinfo了解该模块的相关信息*/
MODULE_AUTHOR("dragon");
MODULE_DESCRIPTION("module learning");
MODULE_ALIAS(" test module");
MODULE_VERSION("2.6.27");
int exportsymbol_test(void)
{
printk("export symbol test\n");
return 0;
}
EXPORT_SYMBOL_GPL(exportsymbol_test);
//EXPORT_SYMBOL(exportsymbol_test);
static int __init hello_init(void)
{
printk("hello init\n");
printk("param1:%sparam2:%d\n", param1, param2);
return 0;
}
static void __exit hello_exit(void)
{
printk("hello exit\n");
printk("param1:%sparam2:%d\n", param1, param2);
return;
}
module_init(hello_init);
module_exit(hello_exit);
知识小结:
1. module_param(参数,类型,权限)
参数(param):变量的名称;
类型(type):变量的类型,包括int,char, charp...;
如果模块以本接口定义了参数,那么:
a) 在insmod 或者 modprobe 加载模块的过程中带有 param=value,那么该param将用外部的value
值取代默认的param值, 否则保持默认值;
b)如果模块在使用了本接口定义了外部接口参数,那么在/proc/modules 文件中会有本模块的加
载信息,同时在/sys/module/模块/ 下的相关子目录下生成有对应的param子目录。例如,如果
定义了module_param(num, int, S_IRUGO), 那么在/sys/module/模块的/moduleparams/ 下生成
有num的文件(这个示不同的linux版本而定),这个文件的值便是该参数模块中的取值。
权限(priority): 正如上述所示,权限指的便是在用户模式下对应的/sys/module/moduleparams/param
文件的访问权限, 因此可知,根据该权限的设置,可以决定应用层能否对模块的运行
参数进行配置。权限有如下的选项:
S_IRUGO: 只读;
S_IWUGO: 可写;
S_IXUGO: 未知;
S_IALLUGO: 包括上述所有的权限;
S_IRWXUGO: 同上;
2. EXPORT_SYMBOL_GPL(参数) / EXPORT_SYMBOL(参数);
上述的两个宏主要是用来导出符号到/proc/kallsyms 文件中,该文件中包含有导出的符号名称和对应的
内存地址。参数中一般是函数名,这样在其他的内核模块中申明后就可以使用该函数,当然,其他的类型
参数同理。
3. 模块的依赖文件:
如果是单一的文件,一般是用
obj-m: 模块.ko;
如果是模块依赖多个文件,那么使用:
obj-m: 模块.ko;
module-objs: file1.o file2.o ... filen.o
4. 模块的注册和注销
模块中是必须使用module_init()和module_exit()分别注册模块的加载函数和退出函数,至于该模块使用
的__init 和 __exit标识,这只是linux 系统的特被标识,以便linux系统在进行相应的操作时候进行
相关的特殊处理,详细的内容会在其他文章叙述。
================================================================================*/