目录
1. 驱动的多文件编译
流程如下
1.1. 准备两个文件
我使用了hello.c和add.c两个文件
hello.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
//static防止别人用重名函数
static int __init hello_init(void)//入口:资源申请
{
printk("SouthernBird\n");
//_init将hello_init放到.init.text段中
return 0;
}
//static防止别人用重名函数
static void __exit hello_exit(void)//出口:资源释放
{
printk("I am leave\n");
//_exit将hello_exit放到.exit.text段中
}
module_init(hello_init);//告诉内核驱动的入口地址
module_exit(hello_exit);//告诉内核驱动的出口地址
MODULE_LICENSE("GPL");//许可证
add.c为空
1.2. 修改Makefile文件
KERNELDIR:=/lib/modules/$(shell uname -r)/build
#KERNELDIR:=/home/hq/temp/kernel-3.4.39/
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
obj-m:=demo.o
demo-y+=hello.o add.o
重点看:obj-m:=demo.o 和 demo-y+=hello.o add.o两句(前面的makefile在我上片帖子已经做了解析)
- obj-m:=demo.o 这一行定义了一个变量obj-m,它指定了要编译生成的目标模块文件的名称为demo.o。该模块文件是通过编译demo.c源文件生成的。
- demo-y+=hello.o add.o 这一行定义了一个变量demo-y,它指定了要编译生成的模块文件所需要的其他对象文件。在这里,hello.o和add.o是要与demo.o一起编译生成的对象文件。
1.3. 执行Make命令生成.ko文件
2. 驱动模块传递参数
2.1. 传递一个参数
2.1.1. 函数原型分析
函数原型:module_param(name, type, perm)
功能: 接收命令行传递的参数
参数:
name:变量名
type:变量类型
perm:权限 0664 0775
2.1.2. 撰写.c文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
//定义变量a
int a=10;
//使用函数
module_param(a, int, 0644);
static int __init hello_init(void)
{
printk("SouthernBird:a is %d\n",a);//打印a的函数
return 0;
}
static void __exit hello_exit(void)
{
printk("I am leave\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
2.1.3. 撰写makefile
KERNELDIR:=/lib/modules/$(shell uname -r)/build
#KERNELDIR:=/home/hq/temp/kernel-3.4.39/
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
obj-m:=hello.o
2.1.4. 编译makefile并验证
不传参数验证
传参验证
2.2. 传递多个参数并使用modeinfo查看驱动信息
2.2.1. 函数原型分析和命令解析
》1.函数原型:MODULE_PARM_DESC(_parm,desc)
功能: 对变量的功能进行描述
参数:
_parm:变量名
desc:描述字段
》2.命令
sudo modeinfo XXXX.ko 查看驱动信息
2.2.2. 撰写.c文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
//定义变量a和b
int a=10;
int b=20;
//使用命令行传参函数
module_param(a,int,0644);
module_param(b,int,0644);
//使用功能描述函数
MODULE_PARM_DESC(a,"this is a");
MODULE_PARM_DESC(b,"this is b");
static int __init hello_init(void)
{
printk("SouthernBird:a is %d\n",a);//打印a的函数
printk("SouthernBird:b is %d\n",b);//打印a的函数
return 0;
}
static void __exit hello_exit(void)
{
printk("I am leave\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
2.2.3. 撰写makefile
KERNELDIR:=/lib/modules/$(shell uname -r)/build
#KERNELDIR:=/home/hq/temp/kernel-3.4.39/
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
obj-m:=hello.o
2.2.4. 编译makefile验证
使用dmesg查看
2.2.5. 使用modeinfo进行查看
sudo modinfo hello.ko
关于变量的描述成功出现
2.3. 传递数组
2.3.1. 分析函数原型
函数原型:module_param_array(name, type, nump, perm)
功能:接收命令行传递的数组
参数:
name:数组名
type:数组类型
nump:参数个数
perm:权限
2.3.2. 撰写.c文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
//定义数组
int ww[10]={0};
//定义module_param_array函数需要的元素个数
int num=0; //这里让num默认为0,通过module_param_array进行改变
//接收命令行传递数组
module_param_array(ww, int,&num, 0644);
static int __init hello_init(void)
{
int i=0;//注意此处i的位置
//在入口打印传递的数组
for(i=0;i<num;i++)
{
printk("ww[%d]:%d\n",i,ww[i]);
}
return 0;
}
static void __exit hello_exit(void)
{
printk("I am leave\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
2.3.3. 撰写makefile文件
KERNELDIR:=/lib/modules/$(shell uname -r)/build
#KERNELDIR:=/home/hq/temp/kernel-3.4.39/
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
obj-m:=hello.o
2.3.4. 编译makefile进行验证
注:按住传递命令行数组时候使用下方命令
sudo insmod hello.ko ww=2,5,6,7
3. 驱动安装完成以后更改变量方法
下面教程,以数组驱动为例
3.1. 查看lsmod可以查看驱动
3.2. 修改驱动变量
3.2.1. 找到路径
一般路径在:/sys/module/驱动模块的名字/parameters
上图就能看到我的驱动只有一个变量ww
3.2.2. 查看变量值
使用
cat <变量名>
3.2.3. 修改变量值
》1.使用
su
进入超级管理员模式
》2.使用
echo <新值> > <变量名>
就可修改变量值