Author-------Dansen-----xzd2734@163.com
编写模块时一般都需要包含头文件<linux/module.h>,而在module.h中定义了符号__module_kernel_version
static const char __module_kernel_version[] __attribute__((section(".modinfo"))) =
"kernel_version=" UTS_RELEASE;
#define UTS_RELEASE "2.4.18-rmk7-pxa1" //include/linux/version.h
符号__module_kernel_version在编译后被放在.o文件的.modinfo段,insmod使用它检查模块和当前内核版本是否匹配.
看到《linux设备驱动程序2》中所说的如果把模块代码分为两块,则需要在另一个文件包含module.h前定义__NO_VERSION__ 使得不再重复定义__module_kernel_version,不过在我的源代码里并没什么用,在我的module.h并没有这种条件包含,而且编译也不会出错,只是用objdump工具察看时,确实在.modinfo出现了两个__module_kernel_version符号。objdump -s hello.o
下面是一个Makefile文件
CC = /opt/host/armv4l/bin/armv4l-unknown-linux-gcc
LD = /opt/host/armv4l/bin/armv4l-unknown-linux-ld
CFLAGS = -D__KERNEL__ -DMODULE -I/HHARM2410-R3/kernel/include -Wall -Wstrict-prototypes -Wno-trigraphs -Os -mapcs -fno-strict-aliasing -fno-common -fno-common -pipe -mapcs-32 -march=armv4 -mtune=arm9tdmi -mshort-load-bytes -msoft-float -I/opt/host/armv4l/src/linux/include
all: hello.o
hello.o: start.o stop.o
$(LD) -r $^ -o $@
.PHONY: clean
clean:
-rm -f *.o
当然是我的ARM平台的,注意CFLAGS,-D__KERNEL__ -DMODULE就相当于在每个文件中define了__KERNEL__和MODULE这两个宏,还要用-I包含内核源码的include目录.
另外来分析一下模块经常用到的一些宏
第一个是 THIS_MODULE,一开始就知道是直向模块自身,但是还是深入研究下吧
在module.h中寻找THIS_MODULE的定义
#if defined(MODULE) && !defined(__GENKSYMS__)
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
#else
#ifndef __GENKSYMS__
#define THIS_MODULE NULL
#endif
#endif
一般不会定义__GENKSYMS__,而编写模块都会定义MODULE,
所以THIS_MODULE是一个struct module类型的指针。
我们把模块编译成一个.o目标文件,其实并没有进行其中的调用进行链接,显然真正的链接过程发生在我们把模块insmod的内核时,而在insmod时内核会创建一个struct module结构的结构体来包容从用户空间load进来的模块,在链接的时候就会把这个指针给THIS_MODULE.
下面这些宏就是在.modinfo段定义一个字符串,没什么可说的。
#define MODULE_AUTHOR(name) /
const char __module_author[] __attribute__((section(".modinfo"))) = /
"author=" name
#define MODULE_DESCRIPTION(desc) /
const char __module_description[] __attribute__((section(".modinfo"))) = /
"description=" desc
下面几个宏会比较复杂
#define MOD_INC_USE_COUNT __MOD_INC_USE_COUNT(THIS_MODULE)
#define MOD_DEC_USE_COUNT __MOD_DEC_USE_COUNT(THIS_MODULE)
#define MOD_IN_USE __MOD_IN_USE(THIS_MODULE)
#define __MOD_INC_USE_COUNT(mod) /
(atomic_inc(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED|MOD_USED_ONCE)
#define __MOD_DEC_USE_COUNT(mod) /
(atomic_dec(&(mod)->uc.usecount), (mod)->flags |= MOD_VISITED)
#define __MOD_IN_USE(mod) /
(mod_member_present((mod), can_unload) && (mod)->can_unload /
? (mod)->can_unload() : atomic_read(&(mod)->uc.usecount))
不过理解了THIS_MODULE看起来就是比较简单了,显然struct module中有对模块使用进行计数的一个变量,我们可以编写简单的模块来打印当前模块结构变量的值
union
{
atomic_t usecount;
long pad;
} uc;
MOD_INC_USE_COUNT就是让usecount加1,MOD_DEC_USE_COUNT让usecount减1
MOD_IN_USE挺复杂,想继续理解就自己继续学习吧。。。编写简单的模块测试比较eazy吧
本文介绍了在Linux内核模块编程中常见的宏,如__module_kernel_version、THIS_MODULE及其作用。讨论了模块编译过程,特别是如何处理__.modinfo段,并通过实例解析了MOD_INC_USE_COUNT、MOD_DEC_USE_COUNT等计数宏的使用。同时,提到了Makefile中的编译选项和模块作者、描述等信息的定义方式。

924

被折叠的 条评论
为什么被折叠?



