module_param(name,type,perm);//将指定的全局变量设置成模块参数
/*
name:全局变量名
type:
使用符号 实际类型 传参方式
bool bool insmod xxx.ko 变量名=0 或 1
invbool bool insmod xxx.ko 变量名=0 或 1
charp char * insmod xxx.ko 变量名="字符串内容"
short short insmod xxx.ko 变量名=数值
int int insmod xxx.ko 变量名=数值
long long insmod xxx.ko 变量名=数值
ushort unsigned short insmod xxx.ko 变量名=数值
uint unsigned int insmod xxx.ko 变量名=数值
ulong unsigned long insmod xxx.ko 变量名=数值
perm:给对应文件 /sys/module/name/parameters/变量名 指定操作权限
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IWUSR 00200
#define S_IXUSR 00100
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010
#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002 //不要用 编译出错
#define S_IXOTH 00001
*/
module_param_array(name,type,&num,perm);
/*
name、type、perm同module_param,type指数组中元素的类型
&num:存放数组大小变量的地址,可以填NULL(确保传参个数不越界)
传参方式 insmod xxx.ko 数组名=元素值0,元素值1,...元素值num-1
*/
可用MODULE_PARAM_DESC宏对每个参数进行作用描述,用法:
MODULE_PARM_DESC(变量名,字符串常量);
字符串常量的内容用来描述对应参数的作用
modinfo可查看这些参数的描述信息
示例:
testparam.c
#include
#include
int gt = 10;
char *gstrr = "hello";
int garr[5] = {1,2,3,4,5};
module_param(gt, int, 0664);
module_param(gstrr, charp, 0664);
module_param_array(garr, int, NULL, 0664);
/* 入口 */
int __init testparam_init(void)
{
int i=0;
printk("gt = %d\n", gt);
printk("gstrr = %s\n", gstrr);
for(i = 0; i < 5; i++) {
printk("%d ", garr[i]);
}
printk("\n");
return 0;
}
/* 出口 */
void __exit testparam_exit(void)
{
printk("testparam will exit\n");
}
MODULE_LICENSE("GPL");
module_init(testparam_init);
module_exit(testparam_exit);
既然内核模块的代码与其它内核代码共用统一的运行环境,也就是说模块只是存在形式上独立,运行上其实和内核其它源码是一个整体,它们隶属于同一个程序,因此一个模块或内核其它部分源码应该可以使用另一个模块的一些全局特性。
一个模块中这些可以被其它地方使用的名称被称为导出符号,所有导出符号被填在同一个表中这个表被称为符号表。
最常用的可导出全局特性为全局变量和函数
查看符号表的命令:nm
nm查看elf格式的可执行文件或目标文件中包含的符号表,用法:
nm 文件名
(可以通过man nm查看一些字母含义)
两个用于导出模块中符号名称的宏:
EXPORT_SYMBOL(函数名或全局变量名)
EXPORT_SYMBOL_GPL(函数名或全局变量名) 需要GPL许可证协议验证
使用导出符号的地方,需要对这些符号进行extern声明后才能使用这些符号
B模块使用了A模块导出的符号,此时称B模块依赖于A模块,则:
补充说明
:
内核符号表(直接当文本文件查看)
/proc/kallsyms运行时 /boot/System.map编译后
modulea.c
#include
#include
int gt = 10; // 全局变量
EXPORT_SYMBOL(gt); //
int __init modulea_init(void)
{
printk("modulea_init gt = %d\n", gt);
return 0;
}
void __exit modulea_exit(void)
{
printk("modulea will exit\n");
}
MODULE_LICENSE("GPL");
module_init(modulea_init);
module_exit(modulea_exit);
moduleb.c
#include
#include
extern int gt; //声明gt变量
int __init moduleb_init(void)
{
printk("moduleb_init gt = %d\n", gt);
return 0;
}
void __exit moduleb_exit(void)
{
printk("moduleb will exit\n");
}
MODULE_LICENSE("GPL");
module_init(moduleb_init);
module_exit(moduleb_exit);
Makefile
ifeq ($(KERNELRELEASE),)
ifeq ($(ARCH),arm)
KERNELDIR ?= /home/myubuntu/Linux_4412/kernel/linux-3.14
ROOTFS ?= /opt/4412/rootfs
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
endif
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules INSTALL_MOD_PATH=$(ROOTFS) modules_install
clean:
rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versions
else
obj-m += modulea.o # 注意编译顺序
obj-m += moduleb.o
endif
/module_a/module_a.c
#include
#include
int gt = 10;
EXPORT_SYMBOL(gt);
int __init module_a_init(void)
{
printk("module_a_init gt = %d\n", gt);
return 0;
}
void __exit module_a_exit(void)
{
printk("module_a will exit\n");
}
MODULE_LICENSE("GPL");
module_init(module_a_init);
module_exit(module_a_exit);
/module_a/Makefile
ifeq ($(KERNELRELEASE),)
ifeq ($(ARCH),arm)
KERNELDIR ?= /home/myubuntu/Linux_4412/kernel/linux-3.14
ROOTFS ?= /opt/4412/rootfs
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
endif
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules INSTALL_MOD_PATH=$(ROOTFS) modules_install
clean:
rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versions
else
obj-m += module_a.o
endif
/module_b/module_b.c
#include
#include
extern int gt;
int __init module_b_init(void)
{
printk("module_b_init gt = %d\n", gt);
return 0;
}
void __exit module_b_exit(void)
{
printk("module_b will exit\n");
}
MODULE_LICENSE("GPL");
module_init(module_b_init);
module_exit(module_b_exit);
/module_b/Makefile
ifeq ($(KERNELRELEASE),)
ifeq ($(ARCH),arm)
KERNELDIR ?= /home/myubuntu/Linux_4412/kernel/linux-3.14
ROOTFS ?= /opt/4412/rootfs
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
endif
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules INSTALL_MOD_PATH=$(ROOTFS) modules_install
clean:
rm -rf *.o *.ko .*.cmd *.mod.* modules.order Module.symvers .tmp_versions
else
obj-m += module_b.o
endif