杂项设备(misc device)在Linux内核驱动开发中有以下典型应用场景:

1. 简单字符设备的快速注册

  • 适用于功能相对简单、不需要复杂设备管理的字符设备
  • 自动分配主设备号(固定为10),只需关心次设备号
  • 简化了传统字符设备的注册流程(无需手动申请设备号、创建类和设备节点)

2. 系统级小工具驱动

  • 看门狗定时器(watchdog)
  • 温度传感器读取
  • LED控制
  • 蜂鸣器控制
  • 按键输入处理

3. 硬件抽象层

  • 为上层应用提供简单的硬件访问接口
  • 例如:GPIO控制、I2C/SPI设备访问、ADC读取等

4. 调试和测试设备

  • 内核模块开发时的测试驱动
  • 提供简单的读写接口用于验证内核与用户空间通信

5. 特殊功能设备

  • 随机数生成器(/dev/random, /dev/urandom)
  • 内存映射设备(/dev/mem, /dev/kmem)
  • 日志设备(/dev/kmsg)

杂项设备的优势:

简化注册流程:只需调用 misc_register(),自动完成设备号分配、设备节点创建 ✅ 统一管理:所有杂项设备共享主设备号10,便于系统管理 ✅ 自动创建设备节点:在 /dev/ 下自动生成设备文件 ✅ 适合小型驱动:代码量少,结构清晰

代码:007_misc.c

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

static int test_open(struct inode *inode,struct file *file)
{
    printk("open\n");
    return 0;
}
static ssize_t test_read(struct file *file,char __user *buf, size_t size,loff_t *off){

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

    *off += size;
    printk("write\n");
    return size;
}
static int test_release(struct inode *inode,struct file *file)
{
    printk("release\n");
    return 0;
}
struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = test_open,
    .read = test_read,
    .write = test_write,
    .release = test_release,
};


MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyl");
MODULE_DESCRIPTION("007_misc");

// 杂项设备
static struct miscdevice misc_dev = {
    .minor = MISC_DYNAMIC_MINOR, //自动分配从设备号
    .name = "007_misc", //设备名称
    .fops = &fops,
};
static int modulecdev_init(void)
{ 
    int ret;
    ret = misc_register(&misc_dev);
    if(ret<0){
        printk(KERN_ERR "misc_register failed!\n");
        return ret;
    }
    printk(KERN_INFO "misc_register success!\n");
    return 0;
}
static void modulecdev_exit(void)
{
    misc_deregister(&misc_dev); //卸载
    printk("modulecdev exit\n");
}

module_init(modulecdev_init);
module_exit(modulecdev_exit);