(本章基于:Linux-4.4.0-37)
Linux驱动中把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体表述),它是一种特殊的字符设备。miscdevice共享一个主设备号MISC_MAJOR(即10),但次设备号不同。 所有的miscdevice设备形成了一个链表,对设备访问时内核根据次设备号查找对应的miscdevice设备,然后调用其file_operations结构中注册的文件操作接口进行操作。
数据结构
<linux/miscdevice.h>
在内核中用struct miscdevice表示miscdevice设备,然后调用其file_operations结构中注册的文件操作接口进行操作。
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
struct list_head list;
struct device *parent;
struct device *this_device;
const char *nodename;
umode_t mode;
};
操作函数
注册
int misc_register(struct miscdevice * misc);
成功注册后会在/dev目录下自动生成一个字符设备文件,主设备号为10,次设备号与文件与之前设置的一致;
注销
int misc_deregister(struct miscdevice *misc);
例:
内核层:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
int my_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "This is miscdevice open\n");
return 0;
}
int my_close(struct inode *inode, struct file *file)
{
printk(KERN_INFO "This is miscdevice close\n");
return 0;
}
const struct file_operations my_fops = {
.open = my_open,
.release = my_close,
};
struct miscdevice my_misc = {
.minor = 201,
.name = "stone",
.fops = &my_fops,
};
static __init int hello_init(void)
{
misc_register(&my_misc);
printk(KERN_ALERT "helloworld!\n");
return 0;
}
static __exit void hello_exit(void)
{
misc_deregister(&my_misc);
printk(KERN_ALERT "helloworld exit!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stone");
用户层:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int
main(void)
{
int fd;
fd = open("/dev/stone", O_RDWR);
if(fd < 0) {
perror("open");
exit(EXIT_FAILURE);
}
close(fd);
return 0;
}