泰山派3M-RK3576-Linux内核驱动教程-Linux驱动基础-字符驱动设备-杂项设备驱动

本章教你如何编写一个杂项设备(misc设备)驱动。杂项设备是 Linux 内核中非常常见的一种字符设备类型,适用于各种简单设备或工具类驱动。它让驱动开发更简单、繁琐的字符设备号管理都交给内核处理。

一、杂项设备简介

杂项设备(misc device)是 Linux 提供的一种特殊字符设备,使用统一的主设备号(一般是10),通过动态分配次设备号来区分不同设备。它简化了设备号分配与节点创建设备,驱动注册流程更简单。

常见的 /dev 目录下的 misc 设备:

  • /dev/rtc
  • /dev/uinput
  • /dev/nvram
  • ...等等

优点:

  • 无需自己分配主设备号
  • 注册流程更省事
  • 适合大多数普通字符设备使用场景

二、杂项设备驱动结构

主要涉及两个结构体和三个操作:

  • struct miscdevice —— 杂项设备描述结构体(核心)
  • struct file_operations —— 设备操作方法表
  • 注册:misc_register()
  • 注销:misc_deregister()

三、快速编写杂项设备驱动

创建一个 08_misc_driver/ 文件夹,在里面创建一个 misc_driver.c 文件,并编写如下代码:

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

// 设备名称
#define DEVICE_NAME "mymiscdev"

/* 设备操作函数表 */
static ssize_t mymisc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    printk(KERN_INFO "mymiscdev: read called\n");
    return 0;
}

static ssize_t mymisc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
    printk(KERN_INFO "mymiscdev: write called\n");
    return 0;
}

/* 设备操作接口 */
static struct file_operations mymisc_fops = {
    .owner = THIS_MODULE,
    .read = mymisc_read,
    .write = mymisc_write,
};

/* 杂项设备描述 */
static struct miscdevice mymiscdev = {
    .minor = MISC_DYNAMIC_MINOR,   // 自动分配次设备号
    .name  = DEVICE_NAME,          // 出现在 /dev 下的名称
    .fops  = &mymisc_fops,
};

/* 模块加载时自动调用 */
static int __init mymiscdev_init(void)
{
    int ret = misc_register(&mymiscdev);
    if (ret)
        printk(KERN_ERR "mymiscdev: register failed\n");
    else
        printk(KERN_INFO "mymiscdev: /dev/%s registered\n", DEVICE_NAME);
    return ret;
}

/* 卸载时自动调用 */
static void __exit mymiscdev_exit(void)
{
    misc_deregister(&mymiscdev);
    printk(KERN_INFO "mymiscdev: /dev/%s removed\n", DEVICE_NAME);
}

module_init(mymiscdev_init);
module_exit(mymiscdev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LCKFB");
MODULE_DESCRIPTION("misc device driver");

1. 设备名和头文件

#define DEVICE_NAME "mymiscdev"

用于指定设备节点的名称,最后节点为 /dev/mymiscdev

2. 设备操作函数(file_operations)

static ssize_t mymisc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
    printk(KERN_INFO "mymiscdev: read called\n");
    return 0;
}
  • .read.write分别实现设备读写操作,目前只是打印日志,并未与用户交换数据,返回0表示操作结束。

3. file_operations结构体

static struct file_operations mymisc_fops = {
    .owner = THIS_MODULE,
    .read = mymisc_read,
    .write = mymisc_write,
};
  • 描述本设备支持的操作(这里只实现了基本读写)。

4. 杂项设备结构体

static struct miscdevice mymiscdev = {
    .minor = MISC_DYNAMIC_MINOR,   // 自动分配次设备号
    .name  = DEVICE_NAME,          // 节点名称
    .fops  = &mymisc_fops,         // 操作方法表
};
  • 这是内核管理杂项设备的核心结构体。
  • minor 设为 MISC_DYNAMIC_MINOR 即自动分配。
  • .name = /dev 下出现的名字。

5. 驱动加载与注销

static int __init mymiscdev_init(void) {
    return misc_register(&mymiscdev);
}
static void __exit mymiscdev_exit(void) {
    misc_deregister(&mymiscdev);
}
  • 加载时注册设备(自动生成 /dev/mymiscdev)。
  • 卸载时注销,节点消失。

四、编译与测试

  1. 编写Makefile
export ARCH=arm64

# 09.杂项设备驱动
export CROSS_COMPILE=/home/lckfb/TaishanPi-3-Linux/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-

# 和源文件名一致
obj-m += misc_driver.o

# 内核源码目录
KDIR := /home/lckfb/TaishanPi-3-Linux/kernel-6.1
PWD ?= $(shell pwd)

all:
    make -C $(KDIR) M=$(PWD) modules

clean:
    make -C $(KDIR) M=$(PWD) clean

和之前编写的 Makefile 几乎一摸一样!

这不过这里变为了 misc_driver.o

  • CROSS_COMPILE:依旧是SDK中的编译器路径前缀。
  • KDIR:依旧是内核源码目录。
  1. 编译驱动

08_misc_driver/ 目录下运行:

make

就会自动生成 .ko 文件,这就是我们所需要的。

  1. 加载模块

misc_driver.ko 复制到开发板中,挂载模块,就能看到 /dev 下生成了我们所需要的设备文件:

sudo insmod misc_driver.ko

五、快速问答

  • Q: 杂项设备和普通字符设备驱动有什么不同? A: 普通字符设备要自己分配设备号、手动注册和创建设备节点,而杂项设备一切让内核自动化,代码更少更方便。
  • Q: 支持多个杂项设备吗? A: 支持的,每个设备维护自己独立的struct miscdevice即可。
  • Q: 设备节点在哪里? A: 由内核自动在/dev下创建,名字就是.name字段,比如上述示例是/dev/mymiscdev

六、总结

  • 杂项设备驱动极大简化了字符设备开发流程。
  • 使用struct miscdevicemisc_register()即可快速完成一个基础驱动。
  • 适合新手开发常见小工具、组件型驱动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值