学习目标:
了解 杂项设备驱动 和普通字符设备的异同,及杂项设备驱动程序的写法
学习内容:
一、杂项设备驱动的特别之处
杂项设备(Miscellaneous Devices)是一种通用的设备类型,用于表示那些不适合其他设备类型的设备。这些设备通常是不规则的,没有标准的通信协议或接口。
在Linux中,把无法归类的设备定义成杂项设备。相对于一般字符设备来说,杂项设备主设备号固定位10。而一般字符设备不管是动态分配还是静态分配设备号,都会一个区别其他类别的唯一主设备号。
杂项设备也会和一般的字符设备一样在/dev下创建设备节点。只是在编写设备驱动时用的函数大有不同。
二、杂项设备编写
1、miscdevice 结构体
杂项设备使用结构体miscdevice 描述,该结构体定义在 include/linux/misdevice.h 文件中。如下图所示:
其中,次设备号minor 一般使用宏 MISC_DYNAMIC_MINOR,表示自动分配次设备号。杂项设备主要依赖次设备号来管理。
#define MISC_DYNAMIC_MINOR 255
name: 就是要告诉系统创建设备节点的名称
fops: 就是系统调用 和 驱动功能的连接桥梁,即包含设备操作的 struct file_operations
结构的指针。
2、杂项设备的注册与卸载
注册和卸载杂项设备的函数声明在 include/linux/miscdevice.h 中,定义在drivers/char/misc.c 文件中。
注册函数 misc_register :
函数原型:int misc_register(struct miscdevice *misc);
参数:杂项设备的结构体指针
返回值:0:成功,负数:失败
卸载函数 misc_deregister:
函数原型:void misc_deregister(struct miscdevice *misc);
参数:杂项设备的结构体指针
3、代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
static int my_misc_open(struct inode *inode, struct file *file)
{
printk("This is my_misc_open\n");
return 0;
}
static ssize_t my_misc_read(struct file *file, char __user *buf, size_t size, loff_t *off)
{
printk("This is my_misc_read\n");
return 0;
}
static ssize_t my_misc_write(struct file *file, const char __user *buf, size_t size, loff_t *off)
{
printk("copy_from_user kbuf = %s\n", kbuf);
return 0;
}
static int my_misc_release(struct inode *inode, struct file *file)
{
printk("This is my_misc_release\n");
return 0;
}
static struct file_operations my_misc_ops={
.owner = THIS_MODULE,
.open = my_misc_open,
.release = my_misc_release,
.read = my_misc_read,
.write = my_misc_write,
};
// 定义杂项设备结构体
struct miscdevice misc_dev={
.minor = MISC_DYNAMIC_MINOR,
.name = "my_misc",
.fops = &my_misc_ops
};
// 驱动入口函数
static int module_misc_init(void)
{
int ret = 0;
ret = misc_register(&misc_dev);
if(ret < 0)
{
printk("misc_register failed\n");
return -1;
}
return 0;
}
// 驱动卸载函数
static void module_misc_exit(void)
{
misc_deregister(&misc_dev);
printk("misc_deregister test module bye!\n");
}
module_init(module_misc_init);
module_exit(module_misc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("BF");
MODULE_VERSION("V1.0");
编译完成后,加载驱动,我们可以查看设备节点中是否创建了杂项设备my_misc,以及主设备号是不是之前说的10, 如图: