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);
}
相关推荐
m0_694845571 小时前
服务器如何配置防火墙规则开放/关闭端口?
linux·服务器·安全·云计算
阿巴~阿巴~2 小时前
Linux基本命令篇 —— alias命令
linux·服务器·bash
好名字更能让你们记住我3 小时前
Linux多线程(十二)之【生产者消费者模型】
linux·运维·服务器·jvm·windows·centos
学习编程的gas3 小时前
Linux开发工具——gcc/g++
linux·运维·服务器
嵌入式成长家3 小时前
ubuntu rules 使用规则
linux·ubuntu·rules 使用规则
_可乐无糖3 小时前
AWS WebRTC: 判断viewer端拉流是否稳定的算法
linux·服务器·webrtc·aws
数据智能老司机3 小时前
Linux内核编程——Linux设备模型
linux·架构·操作系统
BD_Marathon4 小时前
ubuntu防火墙使用
linux·ubuntu
dessler4 小时前
Kafka-消费者(Consumer)和消费者组(Consumer Group)
linux·运维·kafka
kfepiza4 小时前
Debian-10-standard用`networking`服务的`/etc/network/interfaces`配置文件设置多网卡多IPv6
linux·debian