1、简介
Linux 中的三大类驱动:字符设备驱动 、块设备驱动和网络设备驱动。
Linux 驱动有两种运行方式,第一种就是将驱动编译进 Linux 内核中,这样当 Linux 内核启动的时候就会自动运行驱动程序。第二种就是将驱动编译成模块(Linux 下模块扩展名为.ko),在Linux 内核启动以后使用“insmod”命令加载驱动模块。
使用驱动模块有module_init、module_exit两个操作函数,分别在加载时调用和卸载时调用。
static int __init my_module_init(void){
printk("module_init !\r\n");
return 0;
}
static void __exit my_module_exit(void){
printk("module_exit !\r\n");
}
module_init(my_module_init); //注册模块加载函数
module_exit(my_module_exit); //注册模块卸载函数
使用insmod命令加载驱动
insmod xxx.ko
使用rmmod命令卸载驱动
rmmod xxx.ko
使用mknod创建设备节点文件
mknod /dev/xxx c 200 0
#mknod /dev文件 c 主设备号 次设备号
2、添加 LICENSE 和作者信息
要在驱动中加入 LICENSE 信息和作者信息,其中 LICENSE 是必须添加的。
MODULE_LICENSE("GPL"); //添加模块 LICENSE 信息
MODULE_AUTHOR("zuozhe"); //添加模块作者信息
3、Linux 设备号
为了方便管理,Linux 中每个设备都有一个设备号,设备号由主设备号和次设备号两部分组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备。
设备号为unsigned int 类型,是一个 32 位的数据类型。这 32 位的数据构 成了主设备号和次设备号两部分,其中高 12 位为主设备号,低 20 位为次设备号。
1)静态分配设备号
不推荐
2)动态分配设备号
设备号的申请函数如下:
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
函数 alloc_chrdev_region 用于申请设备号,此函数有 4 个参数:
dev:保存申请到的设备号。
baseminor:次设备号起始地址,alloc_chrdev_region 可以申请一段连续的多个设备号,这些设备号的主设备号一样,但是次设备号不同,次设备号以 baseminor 为起始地址地址开始递增。一般 baseminor 为 0,也就是说次设备号从 0 开始。
count:要申请的设备号数量。
name:设备名字。
注销字符设备之后要释放掉设备号,设备号释放函数如下:
void unregister_chrdev_region(dev_t from, unsigned count)
此函数有两个参数:
from:要释放的设备号。
count:表示从 from 开始,要释放的设备号数量。
4、编译驱动程序
Makefile示例
KERNELDIR:=xxx #此为Linux内核路径
CURRENT_PATH := $(shell pwd)
obj-m := xxx.o #此为编译后生成可执行文件名
build: kernel_modules
kernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean