什么是驱动传参
在系统编程中绝大多数情况需要main函数作为程序的入口函数来进行参数的传递。如:
int main(int argc,char **argv){ }
参数说明:
argc英文全称为argument count,代表形参表示传入参数的个数。
argv全称为argument value,代表参数传入的值。
在装载内核模块时,用户可以向模块传递参数,形式为“insmode(或 modprobe)模块名参数名=参数值”,如果不传递,参数将使用模块内定义的缺省值。如果模块被内置,就无法 insmod 了,但是 bootloader可以通过在 bootargs 里设置“模块名.参数名=值”的形式给该内置的模块传递参数。
驱动传参的意义
优势:
1,通过驱动传参,可以让驱动程序史加灵活。兼容性史强。
2.可以通过驱动传参,设置安个校验,防止驱动被盗用。
不足:
1.使驱动代码变得复杂化。
2.增加了驱动的资源占用。
可传递的参数
c语言中常用的数据类型内核大部分都支持驱动传参。这里将内核支持的驱动传递参数
的类型分成三类:
基本类型:char,bool,int,long,short’byte,ushort’uinto
数组:array
字符串:string
怎么给驱动传参数
驱动支持的参数类型有基本类型,数组,字符串。这三个类型分别对应函
module_param:传递基本类型函数
module_param_array:传递数组类型函数
module_param_string:传递字符串类型函数
这三个函数在Linux内核源码include/linux/moduleparam.h中有定义,如下:
#define module_param(name, type, perm) \ module_param_named(name, name, type, perm)
#define module_param_array(name, type, nump, perm) \ module_param_array_named(name, name, type, nump, perm)
#define module_param_string(name, string, len, perm) \ static const struct kparam_string __param_string_##name \ = { len, string }; \ __module_param_call(MODULE_PARAM_PREFIX, name, \ ¶m_ops_string, \ .str = &__param_string_##name, perm, -1, 0);\ __MODULE_PARM_TYPE(name, "string")
传递普通的参数,比如 char int 类型,使用如下函数
传递数组使用以下函数:
部分常用参数权限解释如下:
其它的可以使用下面的方法来判断:
可以将数字最后三位转化为二进制:xxx xxx xxx,高位往低位依次看,第一位为 1 表示文件所有者可读,第二位为 1 表示文件所有者可写,第三位为 1 表示文件所有者可执行;接下来三位表示文件所有者同组成员的权限;再下来三位为不同组用户权限。
include/uapi/linux/stat.h
//user,owner,group // 文件权限 #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 // 执行权限,其他 efine S_IXOTH 00001
include/linux/stat.h
// 定义文件权限掩码 #define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO) // 定义文件所有者、组、其他用户的权限掩码 #define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO) // 定义文件所有者、组、其他用户的读权限掩码 #define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) // 定义文件所有者、组、其他用户的写权限掩码 #define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) // 定义文件所有者、组、其他用户的执行权限掩码 #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
这部分代码定义了一些用于文件权限控制的宏,如S_IRWXUGO、S_IALLUGO、S_IRUGO、S_IWUGO、S_IXUGO等。这些宏可以用于设置文件的权限,以及判断文件的权限。其中,S_IRWXUGO表示所有用户都有读、写、执行权限;S_IALLUGO表示所有用户都有读、写、执行权限,并且设置了set-user-ID、set-group-ID和sticky位;S_IRUGO表示所有用户都有读权限;S_IWUGO表示所有用户都有写权限;S_IXUGO表示所有用户都有执行权限。
MODULE_PARM_DESC函数
函数功能:描述模块参数的信息。在include/linux/moduleparam.h定义
函数原型:MODULE_PARM_DESC(_parm,desc)
函数参数:
_parm:要描述的参数的参数名称。
desc:描述信息。
#include <linux/moduleparam.h> #define MODULE_PARM_DESC(name, desc) __MODULE_PARM_DESC(name, desc)
具体实现
module_param.c
#include <linux/init.h> #include <linux/module.h> #include <linux/moduleparam.h> static int a = 0; static int array[5] = {0}; static int array_size; //static char str[10] = {0}; static char str1[10] = {0}; module_param(a, int, S_IRUGO); MODULE_PARM_DESC(a,"int module param"); module_param_array(array, int, &array_size, S_IRUGO);//自动获取长度 MODULE_PARM_DESC(array,"array module param"); module_param_string(str, str1, sizeof(str1), S_IRUGO); MODULE_PARM_DESC(str,"str module param"); static int module_param_init(void){ int i = 0; printk("a is %d\n",a); for(i = 0;i < array_size;i++){ printk("array[%d] is %d\n",i,array[i]); } printk("array_size is %d\n",array_size); printk("str1 is %s\n",str1); return 0; } static void module_param_exit(void){ printk("module_param exit!!!\n"); } module_init(module_param_init); module_exit(module_param_exit); MODULE_AUTHOR("Paranoid"); MODULE_VERSION("V1.0"); MODULE_LICENSE("GPL");
注意权限设置S_IRUGO,若设置为另外的S_IALLUGO会报错
Makefile
#make 编译项目 #make file 在存放.ko文件目录中创建对应项目的目录 #make install 将*.ko及其应用测试文件移动到根文件中 KERN_DIR = /home/alientek/linux/IMX6ULL/linux/temp/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek ROOTFS_DIR = /home/alientek/linux/nfs/rootfs/experiment #项目名字 PROJECT_NAME = module_param #各驱动名字,ko DRIVER_NAME1 = module_param all: make -C $(KERN_DIR) M=`pwd` modules clear: rm -rf modules.order $(DRIVER_NAME1).mod.c *.o Module.symvers .*.cmd .tmp_versions clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order file: mkdir $(ROOTFS_DIR)/$(PROJECT_NAME) install: cp *.ko $(ROOTFS_DIR)/$(PROJECT_NAME) # 参考内核源码drivers/char/ipmi/Makefile # 要想把a.c, b.c编译成ab.ko, 可以这样指定: obj-m += $(DRIVER_NAME1).o