最简单的hello驱动代码编写
驱动代码编写分为4个部分:
1,头文件
2,驱动模块装载和卸载函数入口到声明
3,实现模块装载和卸载函数入口
4,GPL声明
当ko文件加载到内核时调用装载函数
当ko驱动文件从内核中卸载时会调用卸载函数
//1.头文件
#include <linux/init.h>
#include <linux/module.h>
//3.实现模块装载和卸载函数入口
static int __init hello_drv_init(void)
{
//一般做系统申请资源
printk("-------%s-------------\n", __FUNCTION__);
return 0;
}
static void __exit hello_drv_exit(void)
{
//一般做系统释放资源
printk("-------%s-------------\n", __FUNCTION__);
}
//2.驱动模块装载和卸载函数入口到声明
module_init(hello_drv_init);
module_exit(hello_drv_exit);
//4.GPL声明
MODULE_LICENSE("GPL");
驱动Makefile编写
make
:
判断宏KERNELRELEASE
是否为空,首次编译,其为空
编译第一个规则all
,make -C $(KERNEL_DIR)
进入内核,读取内核中的Makefile,内核中的Makefile会给KERNELRELEASE
赋版本值,继续编译M=$(CUR_DIR) modules
指定当前文件夹为生成module的目标文件夹,但不知道把哪个文件编译成ko。
此时Makefile会再次执行ifeq($(KERNELRELEASE), ),此时,由于之前有赋值,会走else分支,告诉编译器要将hello.c编译成ko文件
ROOTFS_DIR = /opt/4412/rootfs
ifeq ($(KERNELRELEASE), )
# 内核目录 内核源码一定要先编译,参考系统移植时的内核编译
KERNEL_DIR = /home/linux/linux-3.14.10/
CUR_DIR = $(shell pwd)
all :
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
clean :
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
install:
# 将当前目录下的ko模块拷贝到/opt/rootfs/drv_module目录下
cp -raf *.ko $(ROOTFS_DIR)/drv_module
else
# 将hello.c和math.c编译成ko文件
obj-m += hello.o
obj-m += math.o
endif
编译
make
make install
insmod加载ko模块
在开发板上执行,用tftp加载内核和设备树,用nfs挂载根文件系统
加载ko
insmod hello.ko
查看系统中装载过哪些模块
lsmod
卸载ko
mkdir /lib/
rmmod hello
ko模块的传参
加载ko: insmod hello.ko myname=“george” myvalue=33
用途: 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, 0644);
module_param(myname, charp, S_IRUGO|S_IWUSR);
所有的用户都有读权限,只有USR有写权限
#include <linux/init.h>
#include <linux/module.h>
#include <linux/stat.h>
#include "math.h"
//定义参数
static int myvalue = 56;
static char *myname = "peter";
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,22));
return 0;
}
static void __exit hello_drv_exit(void)
{
//一般做系统释放资源
printk("-------%s-------------\n", __FUNCTION__);
}
module_init(hello_drv_init);
module_exit(hello_drv_exit);
MODULE_LICENSE("GPL");
//申明参数
module_param(myvalue, int, 0644);
module_param(myname, charp, S_IRUGO|S_IWUSR);
make
make install
在开发板上执行:
insmod hello.ko myname="zhangsan" myvalue=12
ko模块符号导出
ko模块可以类似动态库文件一样导出接口供其它ko模块使用
步骤如下:
1.编写ko接口文件,如:math.c
2.编写接口头文件声明接口,如:math.h
3.在其它ko模块中调用接口,见:hello.c
4.在Makefile中添加接口模块,见:Makefile
5.编译,make
, make install
6.在开发板上先加载接口ko再加载使用它的ko,insmod math.ko
,insmod hello.ko
//math.c
#include <linux/module.h>
#include <linux/init.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");
//math.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 <linux/stat.h>
#include "math.h"
//定义参数
static int myvalue = 56;
static char *myname = "peter";
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,22));
return 0;
}
static void __exit hello_drv_exit(void)
{
//一般做系统释放资源
printk("-------%s-------------\n", __FUNCTION__);
}
module_init(hello_drv_init);
module_exit(hello_drv_exit);
MODULE_LICENSE("GPL");
//申明参数
module_param(myvalue, int, 0644);
module_param(myname, charp, S_IRUGO|S_IWUSR);
ROOTFS_DIR = /opt/4412/rootfs
ifeq ($(KERNELRELEASE), )
# 内核目录 内核源码一定要先编译
KERNEL_DIR = /home/george/Linux_4412/kernel/linux-3.14
CUR_DIR = $(shell pwd)
all :
make -C $(KERNEL_DIR) M=$(CUR_DIR) modules
clean :
make -C $(KERNEL_DIR) M=$(CUR_DIR) clean
install:
cp -raf *.ko $(ROOTFS_DIR)/drv_module
else
# 将hello.c和math.c编译成ko文件
obj-m += hello.o
obj-m += math.o
endif