Linux系统驱动(四)自动创建设备节点

自动创建设备节点

(一)创建设备节点的机制

1. mknod

将驱动编译到内核中,在内核启动时驱动自动被安装执行

2.devfs(2.4内核)

3. udev(2.6内核至今)

  • 注:hotplug --- 热插拔

(二)API

1. 向上提交目录

c 复制代码
#include <linux/device.h>
struct class * class_create(owner, name)
功能:向上提交目录
参数:
 @owner:THIS_MODULE 这个宏和模块安装卸载相关,并且会记录模块的引用计数值。
 @name:目录名
返回值:成功返回结构体指针,失败返回错误码指针
  • 补:
  • 通过IS_ERR(cls)来判断是否失败。该宏定义在在cls是错误码指针时返回真,否则为假
  • 当cls是错误码指针时,可以通过PTR_ERR(cls)来获得失败返回的错误码

2. 销毁目录

c 复制代码
#include <linux/device.h>
void class_destroy(struct class *cls)
功能:销毁向上提交目录后产生的结构体
参数:
	@cls:结构体指针
返回值:无

3. 向上提交创建节点的信息

c 复制代码
struct device *device_create(struct class *class, struct device *parent,
        dev_t devt, void *drvdata, const char *fmt,...)
功能:向上提交创建节点的信息
参数:
 @class:指向目录的句柄
 @parent:填写为NULL
 @devt:设备号 (241,0)=>(241<<20|0)
        MKDEV(major,minor) //将主和次设备号合成设备号
  		MAJOR(devno);  //从设备号中获取主设备号
  		MINOR(devno);  //从设备号中获取次设备号
 @drvdata:驱动的私有数据,一般填写为NULL。
 @fmt,...:创建节点的名字  "myled%d",i
返回值:成功返回结构体指针,失败返回错误码指针
  • 注:
  • MKDEV(ma,mi) 将主次设备号拼接成设备号
  • MAJOR(devno) 从设备号中获取主设备号
  • MINOR(devno) 从设备号中获取次设备号

4. 销毁节点的信息

c 复制代码
void device_destroy(struct class *class, dev_t devt)
功能:销毁节点的信息
参数:
 @class:指向目录的句柄
 @devt:设备号 (241,0)=>(241<<20|0)
返回值:无

5. IS_ERR(cls)的实现机制

(三)使用示例

功能需求 :在上一篇驱动的基础上加入自动创建设备节点,而无需使用mknod来手动创建
需求分析

设备文件是需要在应用层的open函数就需要使用,因此在驱动中自动创建节点就必须要在mydev_open函数之前实现,因此在mydev_init函数中进行自动创建设备节点,在mydev_exit函数中进行销毁创建的设备节点
代码实现 (此处只展示有修改的代码部分):
LED.c

c 复制代码
static int __init myioctl_init(void){
    //入口注册设备
    major=register_chrdev(0,CHRNAME,&myfops); //第一个参数为0,表示由系统分配主设备号,此时返回值就是系统分配的主设备号
    if(major < 0){//说明出错,返回了错误码,错误码均为负数
        pr_err("register_chrdev error:%d\n",major);
        return major; //失败返回错误码
    }
    printk("major=%d\n",major);
    //向上提交目录
    mycls = class_create(THIS_MODULE,"class_name");
    if(IS_ERR(mycls)){//成功返回结构体指针,失败返回错误码指针
        //为真则说明是错误码指针
        pr_err("class create error:%ld\n",PTR_ERR(mycls));
        return PTR_ERR(mycls); //出错返回错误码
    }
    //向上提交节点信息
    mydev = device_create(mycls,NULL,MKDEV(major,0),NULL,"myioctl");
    if(IS_ERR(mydev)){//成功返回结构体指针,失败返回错误码指针
        //为真则说明是错误码指针
        pr_err("class create error:%ld\n",PTR_ERR(mydev));
        return PTR_ERR(mydev); //出错返回错误码
    }
    return 0; //成功返回0
}

static void __exit myioctl_exit(void){
    //销毁节点信息
    device_destroy(mycls,MKDEV(major,0));
    //销毁目录信息
    class_destroy(mycls);
    //出口销毁设备
    unregister_chrdev(major,CHRNAME);
}
相关推荐
Johny_Zhao1 天前
OpenClaw安装部署教程
linux·人工智能·ai·云计算·系统运维·openclaw
chlk1233 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑3 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件3 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号3 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash4 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI4 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行5 天前
Linux和window共享文件夹
linux
木心月转码ing5 天前
WSL+Cpp开发环境配置
linux
崔小汤呀6 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端