文章目录
驱动模块开发
驱动代码需要有四个部分
1.头文件
2.驱动模块装载和卸载函数入口声明
3.实现模块装载和卸载函数入口
4.GPL声明
编译驱动代码hello.c
在Ubuntu下Samba共享文件夹中组织自己的目录结构
linux@linux:/home/zzw/share/linux-3.14.79/mydirvers/hello_drv$ ls
hello.c hello.mod.o modules.order mymath.h mymath.mod.o
hello.ko hello.o Module.symvers mymath.ko mymath.o
hello.mod.c Makefile mymath.c mymath.mod.c
linux@linux:/home/zzw/share/linux-3.14.79/mydirvers/hello_drv$ pwd
/home/zzw/share/linux-3.14.79/mydirvers/hello_drv
驱动代码hello.c
/*
驱动代码需要有四个部分
1.头文件
2.驱动模块装载和卸载函数入口声明
3.实现模块装载和卸载函数入口
4.GPL声明
*/
//头文件
#include <linux/init.h>
#include <linux/module.h>
//实现模块装载和卸载函数入口
static int __init hello_drv_init(void)
{
//向系统申请资源
printk("-----------%s-------------\n",__FUNCTION__);
return 0;
}
static void __exit hello_drv_exit(void)
{
//释放资源
printk("-----------%s-------------\n",__FUNCTION__);
}
//驱动模块装载和卸载函数入口声明
module_init(hello_drv_init);
module_exit(hello_drv_exit);
//GPL声明
MODULE_LICENSE("GPL");
编写Makefile
- Mkaefile会被读两次
- 第一次是make的时候,这时候主要读取的路径
- 第二次是内核源码变异的时候,这时候,内核源码要知道要- 把该路径下哪个文件编译成ko
例—Makefile
ROOTFS_DIR = /nfs/rootfs / #根文件系统路径
ifeq ($(KERNELRELEASE),)
KERNEL_DIR = /home/zzw/share/linux-3.14.79 #编译过的内核源码的路径
CPU_DIR = $(shell pwd)
all:
make -C $(KERNEL_DIR) M=$(CPU_DIR) modules #把当前路径编成modules
clean:
make -C $(KERNEL_DIR) M=$(CPU_DIR) clean
install:
sudo cp -raf *.ko $(ROOTFS_DIR)/drv_module #把当前的所有.ko文件考到根文件系统的drv_module目录
else
obj-m += hello.o #指定内核要把哪个文件编译成ko
obj-m += mymath.o
endif
insmod 加载ko模块
lsmod 查看系统中装载了哪些模块
rmmod 卸载ko模块
注意:卸载时是驱动名,不加后缀.ko
- 注意:卸载时是驱动名,不加后缀.ko
模块ko参数传递
-
加载模块时insmod hello.ko myname=“zhuzhongwei” myvalue=88参数会传递给模块内部
-
用途
wifi驱动: wifi硬件中内部也运行内部代码,原厂开发,这些代码叫做固件--firmware.bin 装载wifi驱动,必须告诉固件文件在哪里 insmod rtxxx.ko path=/lib/modules/firmware/xxx.bin
-
在代码如何处理参数:
module_param(name, type, perm) 参数1:表示参数到名字,比如myname, myvalue 参数2:参数到类型, charp, int 参数3: /sys/modules/表示文件到权限: 0666
-
用法:
module_param(myvalue, int, 0666); module_param(myname, charp, S_IRUGO|S_IWUGO|S_IXUGO);
-
传参(当驱动内部已经定义了参数后,优先使用外部传入的参数)
ko模块的符号导出
新建mymath.c
#include <linux/init.h>
#include <linux/module.h>
//不需要模块加载和卸载的入口申明,直接定义好一些封装的函数
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_LICENSE("GPL");
新建mymath.h
#ifndef __MATH_H__
#define __MATH_H__
int my_add(int a,int b);
int my_sub(int a,int b);
#endif
hello.c
/*
驱动代码需要有四个部分
1.头文件
2.驱动模块装载和卸载函数入口声明
3.实现模块装载和卸载函数入口
4.GPL声明
*/
//头文件
#include <linux/init.h>
#include <linux/module.h>
#include "math.h"
static int myvalue = 56;
static char *myname = "xinyuan";
//实现模块装载和卸载函数入口
static int __init hello_drv_init(void)
{
//向系统申请资源
printk("-----------%s-------------\n",__FUNCTION__);
printk("name = %s, value = %d\n",myname,myvalue);
printk("a+b = %d, a-b = %d\n",my_add(33,22),my_sub(44,12));
return 0;
}
static void __exit hello_drv_exit(void)
{
//释放资源
printk("-----------%s-------------\n",__FUNCTION__);
}
//驱动模块装载和卸载函数入口声明
module_init(hello_drv_init);
module_exit(hello_drv_exit);
//GPL声明
MODULE_LICENSE("GPL");
//传参(当驱动内部已经定义了参数后,优先使用外部传入的参数)
module_param(myvalue,int,0644);
module_param(myname,charp,S_IRUGO|S_IWUSR);
调用模块符号
- hello.ko里面调用了math.ko中的符号,所以要先加载mymath.ko
#参考
https://blog.csdn.net/m0_37542524/article/details/86522912