【Linux驱动层】iTOP-RK3568学习之路(四):杂项设备驱动框架

一、杂项设备驱动简介


在 Linux 中,把无法归类的五花八门的设备定义成杂项设备。相较于字符设备,杂项设备有以下两个优点:

(1)节省主设备号:杂项设备的主设备号固定为 10,而字符设备不管是动态分配还是静态分配设备号,都会消耗一个主设备号,进而造成了主设备号浪费。当系统中注册了多个 misc 设备驱动时,只需使用子设备号进行区分即可

(2)使用简单:当使用普通的字符设备驱动时,如果开发人员需要导出操作接口给用户空间,就需要注册对应的字符驱动,并创建字符设备 class 从而自动在/dev 下生成设备节点,而 misc驱动只需要将基本信息通过结构体传递给相应处理函数即可。


二、总体框架图


在这里插入图片描述


三、杂项设备相关函数


杂项设备miscdevice 结 构 体

struct miscdevice {
    int minor; 							/* 子设备号 需要用户填写*/
    const char *name;					/* 设备名 需要用户填写*/
    const struct file_operations *fops;	/* 设备操作集 需要用户填写*/
    struct list_head list;
    struct device *parent;
    struct device *this_device;
    const struct attribute_group **groups;
    const char *nodename;
    umode_t mode;
};

定义一个 misc 设备,一般只需要填充 minor、name、fops 这三个成员变量。

  • minor 指次设备号,通常情况下将该参数设置为MISC_DYNAMIC_MINOR,表示自动分配子设备号。
  • name 表示 misc 设备的名字。misc 设备驱动注册成功之后,会在 dev 目录下生成名为 name的设备节点。
  • fops 指向了 file_operations 的结构体,表示字符设备的操作集合。

杂项设备的注册

函数原型:
	int misc_register(struct miscdevice *misc);
函数作用:
	基于misc_class构造一个设备,将miscdevice结构挂载到misc_list列表上,
    并初始化与linux设备模型相关的结构。进而起到杂项设备注册的作用。
参数含义:
	misc: 杂项设备的结构体指针
函数返回值:
    申请成功返回 0,申请失败返回负数

杂项设备的卸载

函数原型:
	int misc_deregister(struct miscdevice *misc);
函数作用:
	从 mist_list 中删除 miscdevice,进而起到杂项设备卸载的作用。
参数含义:
	misc: 杂项设备的结构体指针
函数返回值:
    卸载成功返回 0,申请失败返回负数

四、实例代码


#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>


static int cdev_test_open(struct inode * inode, struct file * file){
    printk("This is cdev_test_open!\n");
    return 0;
}


static ssize_t cdev_test_read(struct file * file, char __user *buf, size_t size, loff_t *off){
    printk("This is cdev_test_read!\n");
    return 0;
}


static ssize_t cdev_test_write(struct file * file, const char __user * buf, size_t size, loff_t *off){
    printk("This is cdev_test_write!\n");
    return 0;
}


static int cdev_test_release(struct inode * inode, struct file * file){
    printk("This is cdev_test_release!\n");
    return 0;
}


struct file_operations cdev_test_ops={
    .owner = THIS_MODULE,    // 文件操作结构体
    .open = cdev_test_open,
    .read = cdev_test_read,
    .write = cdev_test_write,
    .release = cdev_test_release,
};


struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "test",
    .fops = &cdev_test_ops
};


static int chardev_init(void){
    int ret;     //返回值判断

    ret = misc_register(&misc_dev);     //注册杂项设备
    if (ret < 0)
    {
        printk("misc_register failed\r\n");
    }
    printk("misc_register ok\r\n");

    return 0;
}


static void chardev_exit(void){
    misc_deregister(&misc_dev);  //卸载杂项设备
    printk("chardev_exit!\n");
}


module_init(chardev_init);
module_exit(chardev_exit);


MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("ZSY");
MODULE_VERSION("V1.0");



最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-22 06:12:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-22 06:12:05       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-22 06:12:05       82 阅读
  4. Python语言-面向对象

    2024-04-22 06:12:05       91 阅读

热门阅读

  1. 记录mac上图像处理

    2024-04-22 06:12:05       39 阅读
  2. 面:go能不能手写一个简单的协程池?

    2024-04-22 06:12:05       40 阅读
  3. 【LeetCode热题100】【动态规划】零钱兑换

    2024-04-22 06:12:05       35 阅读
  4. 力扣练习题(2024/4/17)

    2024-04-22 06:12:05       34 阅读
  5. 实现动态组件的方式

    2024-04-22 06:12:05       33 阅读
  6. linux环境下创建网口聚合实例

    2024-04-22 06:12:05       32 阅读
  7. 子组件向父组件传参的方式?

    2024-04-22 06:12:05       42 阅读
  8. MySQL数据库——11、MySQL LIKE 子句

    2024-04-22 06:12:05       36 阅读
  9. [面向对象程序设计]包含警戒

    2024-04-22 06:12:05       40 阅读