自动创建设备节点-12

Posted 杨斌并

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动创建设备节点-12相关的知识,希望对你有一定的参考价值。

自动创建设备节点

怎么自动创建一个设备节点?

在嵌入式 Linux中使用mdev来实现设备节点文件的自动创建和删除。

什么是mdev?

mdev是 udev 的简化版本,是busybox中所带的程序,最适合用在嵌入式系统。

什么是udev?

udev是一种工具,它能够根据系统中的代设答的状杏更奇备艺计件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。udev一般用在此上的 linux中,相对 mdev来说要复杂些。

怎么自动创建设备节点?

  • 自动创建设备节点分为俩个步骤:
  1. 步骤一:使用class_create函数创建一个class的类。
  2. 步骤二:使用device_create函数在我们创建的类下面创建一个设备。

创建和删除类函数

  • 在Linux驱动程序中一般通过两个函数来完成设备节点的创建和删除。首先要创建一个class类结构体,
  • class结构体定义在include/linux/device,h里面。
  • class_create是类创建函数,class_create是个宏定义,

内容如下:

#define class_create(owner, name)    

({           

  static struct lock_class_key __key; 

  __class_create(owner, name, &__key);  

})
  • class_create 一共有两个参数,

  • 参数owner一般为THIS_MpDULE,

  • 参数 name是类名字。

  • 返回值是个指向结构体class的指针,也就是创建的类。

  • //使用这个会查看到生成的类名
    ls  /sys/class 
    

卸载驱动程序的时候需要删除掉类,类删除函数为class_destroy,函数原型如下:

void class_destroy(struct class *cls);
  • 参数cls就是要删除的类。

创建设备函数

当使用上节的函数创建完成一个类后,使用device_create 函数在这个类下创建一个设备。

  • device_create函数原型如下:
struct device *device_create(struct class *class,_struct device *parent,dev_ t devt, void *drvdata,const char*fmt,...)

device_create是个可变参数函数,参数class 就是设备要创建哪个类下面;

  • 参数 parent是父设备,一般为NULL,也就是没有父设备;
  • 参数 devt是设备号;
  • 参数drvdata是设备可能会使用的一些数据,一般为NULL;
  • 参数fmt是设备名字,如果设置fmt=xxx的话,就会生成/dev/xxx这个设备文件。返回值就是创建好的设备。
  • 会在dev/目录下生成改节点

代码

  • app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[]){
    int fd;
    char buf[64] = {0};
    char buf_write[64] = "write aaaaaaaaa";
    fd = open("/dev/chrdev_test",O_RDWR);
    if (fd < 0)
    {
        printf("open error \\n");
        return fd;
    }
    // printf("open success \\n");
    // read(fd,buf,sizeof(buf));
    // write(fd,buf_write,sizeof(buf_write));
    // printf("buf is %s\\n",buf);
    // close(fd);
    return 0;
}

-chrdev.c

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

//设备的数量
#define DEVICE_NUMBER 1
//静态名称
#define DEVICE_SNAME "schrdev"
//动态名称
#define DEVICE_ANAME "achrdev"
//次设备号的起始地址
#define DEVICE_MINOR_NUMBER 0
//类的名字
#define DEVICE_CLASS_NAME "chrdev_class"
#define DEVICE_NODE_NAME "chrdev_test"

//主设备号,次设备号
static int major_num, minor_num;
//设备号
dev_t dev_num;

struct cdev cdev;

module_param(major_num,int,S_IRUSR);
module_param(minor_num,int,S_IRUSR);

int chrdev_open(struct inode * inode, struct file * file){

    printk("chrdev_open 已经打开了");
    return 0;

}

struct file_operations chrdev_ops =
{

    .owner = THIS_MODULE,
    .open = chrdev_open, 
  
};

struct class *class;
struct device *device;

static int hello_init(void){

    int ret;

    if (major_num)
    {
        dev_num = MKDEV(major_num, minor_num);

        printk("major_num = %d \\n",major_num);
        printk("minor_num = %d \\n",minor_num);

        ret = register_chrdev_region(dev_num,DEVICE_NUMBER,DEVICE_SNAME);

        if (ret <0 )
        {
            printk("register_chrdev_region 注册失败了 \\n");
        }

        printk("register_chrdev_region 注册成功了 \\n");      

    }else 
    {

        ret = alloc_chrdev_region(&dev_num, DEVICE_MINOR_NUMBER, DEVICE_NUMBER, DEVICE_ANAME);
        if (ret < 0 )
        {
            printk("alloc_chrdev_region 失败了 \\n");
        }

        major_num = MAJOR(dev_num);
        minor_num = MINOR(dev_num);

        printk("major_num = %d \\n",major_num);
        printk("minor_num = %d \\n",minor_num);

        printk("alloc_chrdev_region 成功了 \\n");
        
    }


    cdev.owner = THIS_MODULE;
    cdev_init(&cdev, &chrdev_ops);

    cdev_add(&cdev, dev_num, DEVICE_NUMBER);
    
    class = class_create(THIS_MODULE, DEVICE_CLASS_NAME);

    device_create(class, NULL, dev_num, NULL, DEVICE_NODE_NAME);
    
    printk(KERN_ALERT "Hello , World\\n"); //内核空间里没有printf,用printk
    return 0;

}

static void hello_exit(void){
    unregister_chrdev_region(MKDEV(major_num, minor_num), DEVICE_NUMBER);
    cdev_del(&cdev);
    device_destroy(class,dev_num);
    class_destroy(class);
    printk(KERN_ALERT "Goodbye 注销成功 , World\\n");
}

//模块的注册
module_init(hello_init);
//模块的卸载
module_exit(hello_exit);
MODULE_LICENSE("Dual BSD/GPL");

以上是关于自动创建设备节点-12的主要内容,如果未能解决你的问题,请参考以下文章

如何自动创建设备节点

linux字符设备-自动创建设备号和设备节点

字符设备驱动程序自动创建设备节点详解

Linux-设备节点文件创建函数

class_create(),device_create自动创建设备文件结点

正点原子I.MX6U-MINI驱动篇3新字符设备驱动实验newchrled,自动创建设备节点