linux misc混杂设备驱动

一. misc结构体

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;//mode_t mode;//};

二. 设备号 misc设备的主设备号为10

#define MISC_MAJOR10

三. misc设备系统的初始化 misc_init

static int __init misc_init(void){int err;#ifdef CONFIG_PROC_FSproc_create("misc", 0, NULL, &misc_proc_fops);#endifmisc_class = class_create(THIS_MODULE, "misc");//创建目录"/sys/class/misc"err = PTR_ERR(misc_class);if (IS_ERR(misc_class))goto fail_remove;err = -EIO;if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))//注册为字符设备,捆绑操作函数集goto fail_printk;misc_class->devnode = misc_devnode;return 0;fail_printk:printk("unable to get major %d for misc devices\n", MISC_MAJOR);class_destroy(misc_class);fail_remove:remove_proc_entry("misc", NULL);return err;}

再看一下register_chrdev

static inline int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops){return __register_chrdev(major, 0, 256, name, fops);}

这里直接根据主设备号创建256个设备,256=2^8,所以它是把所有的杂项设备都给注册成字符设备了misc_fops作为这所有misc设备捆绑的操作函数集

static const struct file_operations misc_fops = {.owner= THIS_MODULE,.open= misc_open,.llseek= noop_llseek,};

在misc_open中,也就是我们打开misc设备的时候,misc_open方法会为我们捆绑自定义的操作函数集

static int misc_open(struct inode * inode, struct file * file){int minor = iminor(inode);//根据设备节点获取次设备号struct miscdevice *c;int err = -ENODEV;const struct file_operations *old_fops, *new_fops = NULL;mutex_lock(&misc_mtx);list_for_each_entry(c, &misc_list, list) {//遍历misc_list查看次设备是否注册(misc_list元素在设备注册时添加)if (c->minor == minor) {new_fops = fops_get(c->fops);//获取自定义的操作函数集break;}}if (!new_fops) {//若找不到则再找一次,还不行errormutex_unlock(&misc_mtx);request_module("char-major-%d-%d", MISC_MAJOR, minor);mutex_lock(&misc_mtx);list_for_each_entry(c, &misc_list, list) {if (c->minor == minor) {new_fops = fops_get(c->fops);break;}}if (!new_fops)goto fail;}err = 0;old_fops = file->f_op;//获取指向旧的设备操作函数集(misc_fops)指针file->f_op = new_fops;//文件操作函数集指针指向新的操作函数集if (file->f_op->open) {//若存在open方法file->private_data = c;err=file->f_op->open(inode,file);//则调用其自定义的open方法if (err) {fops_put(file->f_op);file->f_op = fops_get(old_fops);}}fops_put(old_fops);//释放旧的函数集指针fail:mutex_unlock(&misc_mtx);return err;}

四. misc设备注册 misc_register

int misc_register(struct miscdevice * misc){struct miscdevice *c;dev_t dev;int err = 0;INIT_LIST_HEAD(&misc->list);//初始化链表头mutex_lock(&misc_mtx);list_for_each_entry(c, &misc_list, list) {//遍历misc_listif (c->minor == misc->minor) {//查看设备号是否被占用mutex_unlock(&misc_mtx);return -EBUSY;}}if (misc->minor == MISC_DYNAMIC_MINOR) {//判断是否指定要动态分配次设备号int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);//查找可用次设备号if (i >= DYNAMIC_MINORS) {mutex_unlock(&misc_mtx);return -EBUSY;}misc->minor = DYNAMIC_MINORS - i - 1;//分配次设备号set_bit(i, misc_minors);//设置占用标志位}dev = MKDEV(MISC_MAJOR, misc->minor);//根据主次设备号获取设备号misc->this_device = device_create(misc_class, misc->parent, dev,misc, "%s", misc->name);//添加设备文件"/dev/xxx"if (IS_ERR(misc->this_device)) {int i = DYNAMIC_MINORS - misc->minor - 1;if (i < DYNAMIC_MINORS && i >= 0)clear_bit(i, misc_minors);err = PTR_ERR(misc->this_device);goto out;}/* * Add it to the front, so that later devices can "override" * earlier defaults */list_add(&misc->list, &misc_list);//将设备链表头添加到misc_list中 out:mutex_unlock(&misc_mtx);return err;}

五. misc设备注销 misc_deregister

int misc_deregister(struct miscdevice *misc){int i = DYNAMIC_MINORS - misc->minor - 1;//通过次设备号计算出位标志if (WARN_ON(list_empty(&misc->list)))return -EINVAL;mutex_lock(&misc_mtx);list_del(&misc->list);//从misc_list删除设备链表头device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));//删除设备节点if (i < DYNAMIC_MINORS && i >= 0)clear_bit(i, misc_minors);//清除位标志mutex_unlock(&misc_mtx);return 0;}

六. misc简单实例

#include <linux/fs.h>#include <linux/module.h>#include <linux/miscdevice.h>static int test_open(struct inode * inode, struct file * filp){return 0;}static const struct file_operations test_fops = {.owner = THIS_MODULE,.open  = test_open,};static struct miscdevice misc_dev={.minor=MISC_DYNAMIC_MINOR,.name="misc_test",.fops=&test_fops};static int __init test_init(void){return misc_register(&misc_dev);}static void __exit  test_exit(void){misc_deregister(&misc_dev);}module_init(test_init);module_exit(test_exit);MODULE_LICENSE("GPL");

七. 查看misc信息的方法

加载模块后

lsmod |grep testtest                     829  0 
ls -l /dev/misc_test crw-rw---- 1 root root 10, 54 2012-12-18 10:28 /dev/misc_test
ls -l /sys/class/misc/ |grep misc_testlrwxrwxrwx 1 root root 0 2012-12-18 10:33 misc_test -> ../../devices/virtual/misc/misc_test
cat /proc/misc |grep misc_test 54 misc_test

谁是谁生命的点缀。

linux misc混杂设备驱动

相关文章:

你感兴趣的文章:

标签云: