一、程序分析及源码
1.杂项设备是字符设备的封装,主设备号固定为10,省去手动申请设备号、创建 class、cdev 初始化等步骤,API更加精简。
2.源码
misc_demo.c
#include<linux/init.h>#include<linux/module.h>#include<linux/miscdevice.h>#include<linux/fs.h>// 步骤1:定义杂项设备结构体static struct miscdevice misc_dev;// 驱动回调函数staticintmisc_open(struct inode *inode, struct file *file){ printk("打开杂项设备\n"); return 0;}staticssize_tmisc_read(struct file *file, char __user *buf, size_t len, loff_t *off){ printk("读取杂项设备\n"); return 0;}staticssize_tmisc_write(struct file *file, constchar __user *buf, size_t len, loff_t *off){ printk("写入杂项设备\n"); return len;}staticintmisc_release(struct inode *inode, struct file *file){ printk("关闭杂项设备\n"); return 0;}// 步骤2:定义文件操作集static const struct file_operations misc_fops = { .owner = THIS_MODULE, .open = misc_open, .read = misc_read, .write = misc_write, .release = misc_release,};staticint __init misc_init(void){ // 填充miscdevice结构体:次设备号、设备名称、文件操作集 misc_dev.minor = MISC_DYNAMIC_MINOR; // 动态分配次设备号 misc_dev.name = "misc_demo"; // /dev/misc_demo misc_dev.fops = &misc_fops; // 步骤3:注册杂项设备进内核,一条API完成全部注册 int ret = misc_register(&misc_dev); if(ret < 0) { printk("杂项设备注册失败\n"); return ret; } printk("杂项设备驱动加载成功,节点:/dev/misc_demo\n"); return 0;}staticvoid __exit misc_exit(void){ // 卸载杂项设备 misc_deregister(&misc_dev); printk("杂项驱动卸载完毕\n");}module_init(misc_init);module_exit(misc_exit);MODULE_LICENSE("GPL");MODULE_DESCRIPTION("最简misc杂项设备驱动");
Makefile
obj-m += misc_demo.o #obj-m 是在 Linux 内核模块开发里常被使用的一个变量 #在 Linux 内核源码的 Makefile 体系中,obj-m 变量 #的用途是指明要构建成内核模块(.ko 文件)的目标文件#指定Linux内核源码路径KDIR := /srv/samba/shared/day7/linux-xlnx-masterPWD := $(shell pwd)default:$(MAKE) -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modulesclean:$(MAKE) -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- clean
二、测试
三、环境配置请参考如下文章
参考<Linux下驱动开发模型之普通字符模型>