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);
}
相关推荐
AGI学习社7 分钟前
2024中国排名前十AI大模型进展、应用案例与发展趋势
linux·服务器·人工智能·华为·llama
H.2028 分钟前
centos7执行yum操作时报错Could not retrieve mirrorlist http://mirrorlist.centos.org解决
linux·centos
9毫米的幻想1 小时前
【Linux系统】—— 编译器 gcc/g++ 的使用
linux·运维·服务器·c语言·c++
helloliyh1 小时前
Windows和Linux系统安装东方通
linux·运维·windows
van叶~3 小时前
Linux探秘坊-------4.进度条小程序
linux·运维·小程序
秋风&萧瑟3 小时前
【数据结构】顺序队列与链式队列
linux·数据结构·windows
我科绝伦(Huanhuan Zhou)3 小时前
Linux 系统服务开机自启动指导手册
java·linux·服务器
hunter2062065 小时前
ubuntu终端当一段时间内没有程序运行时,自动关闭终端。
linux·chrome·ubuntu
代码讲故事7 小时前
从Windows通过XRDP远程访问和控制银河麒麟ukey v10服务器,以及多次连接后黑屏的问题
linux·运维·服务器·windows·远程连接·远程桌面·xrdp
qq_243050799 小时前
irpas:互联网路由协议攻击套件!全参数详细教程!Kali Linux入门教程!黑客渗透测试!
linux·网络·web安全·网络安全·黑客·渗透测试·系统安全