91.内核模块实验2

一、模块参数

根据不同应用场合向 内核模块 传递不同参数,提高内核模块灵活性。

定义一个常见变量可以通过使用 module_param 宏 把传参值赋给变量。
然后在shell下: insmod xxx.ko key1=val1 key2=val2 ... 可以将参数传递给此内核模块。

module_param(name, type, perm)
name:参数名
type:参数类型,如int、byte、bool、...
		注意 char 在此处应该使用 byte,char* 在此处应该使用 charp。
perm:读写权限,注意不允许设置可执行权限,八进制数串,以0开头,如0777

模块加载以后,可以在 /sys/module/模块名/parameters 目录下,会生成该参数对应的同名文件(对应变量需指明 r 权限),cat其可以打印变量值,该文件的内容与对应变量的实时值同步。

模块卸载以后,这些变量同名文件消失。

注意函数第三个参数 perm 若rwx中的r权限不开,你会发现这些变量同名文件不存在。
开了w权限可以在shell下修改其值。另外开了 w 权限必须也要开 r 权限,否则编译报错。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

/*
 * itype 未指定读权限,在 /sys/module/test/parameter
 * 目录下找不到该变量名,下面三个变量都能在该目录下体现
 */
static int itype=0;
module_param(itype,int,0);

static bool btype=0;
module_param(btype,bool,0644);

/* 注意字符类型对应下面第二个参数:byte */
static char ctype=0;
module_param(ctype,byte,0644);

/* 注意字符指针类型对应下面第二个参数:charp */
static char  *stype=0;
module_param(stype,charp,0644);

static int __init param_init(void) {
 	printk(KERN_ALERT "param init!\n");
	printk(KERN_ALERT "itype=%d\n",itype);
	printk(KERN_ALERT "btype=%d\n",btype);
	printk(KERN_ALERT "ctype=%d\n",ctype);
	printk(KERN_ALERT "stype=%s\n",stype);
	return 0;
}

static void __exit param_exit(void) {
 	printk(KERN_ALERT "module exit!\n");
 	printk(KERN_ALERT "itype=%d\n",itype);
	printk(KERN_ALERT "btype=%d\n",btype);
	printk(KERN_ALERT "ctype=%d\n",ctype);
	printk(KERN_ALERT "stype=%s\n",stype);
}

module_init(param_init);
module_exit(param_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("author");
MODULE_DESCRIPTION("module_param");
MODULE_ALIAS("module_param");
  • 测试
    只有指定了 读权限,才能在 /sys/module/模块名/parameters 目录下看到对应的模块参数名。
    只有指定了 写权限 ,才改变这个模块参数变量的值。
    不指定 读权限 指定 写权限 ,编译报错。
    echo 1 个字串1个文件 ,会自动添加 1个换行符null-terminated 之前。
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # modprobe test.ko itype=66 btype=1 ctype='6' stype="666"
param init!
itype=66
btype=1
ctype=6
stype=666
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # ls  /sys/module/test/parameters/
btype  ctype  stype
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # cat /sys/module/test/parameters/btype 
Y
/lib/modules/4.1.15 # cat /sys/module/test/parameters/ctype 
6
/lib/modules/4.1.15 # cat /sys/module/test/parameters/stype 
666
/lib/modules/4.1.15 # echo "888" > /sys/module/test/parameters/stype
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # cat /sys/module/test/parameters/stype 
888

/lib/modules/4.1.15 # rmmod test
module exit!
itype=66
btype=1
ctype=6
stype=888

/lib/modules/4.1.15 # 

二、符号共享

内核模块可以共享 导出的符号表 ,然后在不同的内核模块之间共享。

可以导出 / 共享 变量 或者 函数

通过此宏进行变量或者函数的导出。
EXPORT_SYMBOL(sym);
// sym:变量名或者函数名
// 注意使用别的模块的变量函数的模块也要在其c文件中包含声明的头文件,否则gcc编译都不过了

1、查看符号表

cat /proc/kallsyms | grep xxx

xxx 是想要查询的符号名称。

2、模块手动加载

insmod
rmmod

加载时,必须先加载相关依赖模块。
卸载时,顺序相反。

3、模块自动加载

所有内核模块需要统一放到 /lib/modules/内核版本 目录下:cp *.ko /lib/modules/内核版本

自动建立模块依赖关系:depmod -a ,建立完毕可以查看模块依赖关系: cat /lib/modules/内核版本/modules.dep

加载模块及其依赖模块:modprobe xxx(注意用 modprobe 加载模块时可以自动预加载此模块依赖的模块)。

卸载模块及其依赖模块(.ko 后缀名可以省略):modprobe -r xxx (会自动卸载)。

4、模块加载卸载总结

insmod xxx.ko :加载内核模块,若此模块依赖别的内核模块,需要事先手动加载好(.ko 后缀名不可以省略,必须要在模块所在目录)。
modprobe xxx.ko : 加载内核模块,若此模块依赖别的内核模块,会自动去加载(.ko 后缀名可以省略,不必要在模块所在目录)。
rmmod xxx.ko :卸载内核模块,只卸载当前模块(.ko 后缀名可以省略,不必要在模块所在目录)。
modprobe -r xxx.ko :卸载内核模块,该模块依赖的其它模块也会被卸载(.ko 后缀名可以省略,不必要在模块所在目录)。
modprobe 会自动分析模块的依赖关系,cat /lib/modules/内核版本/modules.dep 可以获取当前模块的依赖关系。
rmmod xxx.ko卸载某个模块时,若这个模块被另一个模块依赖,那么会报错。

  • module_param.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

static int itype=0;
module_param(itype,int,0);

static bool btype=0;
module_param(btype,bool,0644);

/* 注意字符类型对应下面第二个参数:byte */
static char ctype=0;
module_param(ctype,byte,0);

/* 注意字符指针类型对应下面第二个参数:charp */
static char  *stype=0;
module_param(stype,charp,0644);

static int __init param_init(void) {
 	printk(KERN_ALERT "param init!\n");
	 printk(KERN_ALERT "itype=%d\n",itype);
	 printk(KERN_ALERT "btype=%d\n",btype);
	 printk(KERN_ALERT "ctype=%d\n",ctype);
	 printk(KERN_ALERT "stype=%s\n",stype);
	 return 0;
}

static void __exit param_exit(void) {
 	printk(KERN_ALERT "module exit!\n");
 	printk(KERN_ALERT "itype=%d\n",itype);
	printk(KERN_ALERT "btype=%d\n",btype);
	printk(KERN_ALERT "ctype=%d\n",ctype);
	printk(KERN_ALERT "stype=%s\n",stype);
}
/* 导出变量 */
EXPORT_SYMBOL(itype);

int my_add(int a, int b) {
    return a+b;
}
/* 导出函数 */
EXPORT_SYMBOL(my_add);

int my_sub(int a, int b) {
    return a-b;
}
/* 导出函数 */
EXPORT_SYMBOL(my_sub);

module_init(param_init);
module_exit(param_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("author");
MODULE_DESCRIPTION("module_param");
MODULE_ALIAS("module_param");
  • calculation.h
#ifndef __CALCULATION_H__
#define __CALCULATION_H__

extern int itype;


int my_add(int a, int b);
int my_sub(int a, int b);

#endif
  • calculation.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
/* 这个头文件声明了导出的变量和函数的声明。 */
#include "calculation.h"

static int __init calculation_init(void)
{
	printk(KERN_ALERT "calculation  init!\n");
    printk(KERN_ALERT "itype+1 = %d, itype-1 = %d\n", my_add(itype,1), my_sub(itype,1));    
    return 0;
}

static void __exit calculation_exit(void)
{
	printk(KERN_ALERT "calculation  exit!\n");
}


module_init(calculation_init);
module_exit(calculation_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("author");
MODULE_DESCRIPTION("calculation module");
MODULE_ALIAS("calculation_module");
  • 测试
    只有不被依赖的模块才能被卸载(rmmodmodprobe -r ),modprobe -r 会把要卸载模块及其依赖的模块一并卸载掉。。
    上面的两个 c文件可以分来编译,只要加载的顺序对了就可以。
    卸载的顺序和加载的顺序相反。
/lib/modules/4.1.15 # modprobe test.ko itype=66 btype=1 ctype='6' stype="666"
param init!
itype=66
btype=1
ctype=6
stype=666
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # modprobe a.ko 
calculation  init!
itype+1 = 67, itype-1 = 65
/lib/modules/4.1.15 # rmmod test.ko 
rmmod: can't unload module 'test': Resource temporarily unavailable
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # modprobe -r test
modprobe: can't unload module 'test': Resource temporarily unavailable
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # lsmod
Module                  Size  Used by    Tainted: G  
a                        713  0 
test                    1815  1 a
/lib/modules/4.1.15 # 
/lib/modules/4.1.15 # rmmod a
calculation  exit!
/lib/modules/4.1.15 # rmmod test
module exit!
/lib/modules/4.1.15 # 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值