linux 内核模块中的宏

本文介绍了在Linux内核模块编程中常见的宏,如__module_kernel_version、THIS_MODULE及其作用。讨论了模块编译过程,特别是如何处理__.modinfo段,并通过实例解析了MOD_INC_USE_COUNT、MOD_DEC_USE_COUNT等计数宏的使用。同时,提到了Makefile中的编译选项和模块作者、描述等信息的定义方式。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

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吧
 

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值