zoukankan      html  css  js  c++  java
  • 如何自动创建设备节点

    创建设备文件的方法:

    第一种是使用mknod手工创建:mknod filename type major minor

    第二种是自动创建设备节点:利用udev(mdev)来实现设备文件的自动创建,首先应保证支持udev(嵌入式系统用mdev),由busybox配置

    udev介绍

    udev 运行在用户模式,而非内核中udev 的初始化脚本在系统启动时创建设备节点,并且当插入新设备——加入驱动模块——在sysfs上注册新的数据后,udev会创新新的设备节点

         udev 是一个工作在用户空间的工具,它能根据系统中硬件设备的状态动态的更新设备文件,包括设备文件的创建,删除,权限等。这些文件通常都定义在/dev 目录下,但也可以在配置文件中指定。udev 必须内核中的sysfs和tmpfs支持,sysfs 为udev 提供设备入口和uevent 通道,tmpfs 为udev 设备文件提供存放空间

        注意,udev 是通过对内核产生的设备文件修改,或增加别名的方式来达到自定义设备文件的目的。但是,udev 是用户模式程序,其不会更改内核行为。也就是说,内核仍然会创建sda,sdb等设备文件,而udev可根据设备的唯一信息来区分不同的设备,并产生新的设备文件(或链接)。而在用户的应用中,只要使用新产生的设备文件

    动创建设备节点:

    在驱动用加入对udev 的支持主要做的就是:在驱动初始化的代码里调用class_create(...)为该设备创建一个class,再为每个设备调用device_create(...)创建对应的设备

        内核中定义的struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。

         这样,加载模块的时候,用户空间中的udev会自动响应 device_create()函数,去/sysfs下寻找对应的类从而创建设备节点。

    1、class_create(...) 函数

    功能:创建一个类;

    #define class_create(owner, name)         
    ({                        
        static struct lock_class_key __key;   
        __class_create(owner, name, &__key);      
    })  

    owner:THIS_MODULE
    name  : 名字

    __class_create(owner, name, &__key)源代码如下:

    struct class *__class_create(struct module *owner, const char *name,  
                     struct lock_class_key *key)  
    {  
        struct class *cls;  
        int retval;  
      
        cls = kzalloc(sizeof(*cls), GFP_KERNEL);  
        if (!cls) {  
            retval = -ENOMEM;  
            goto error;  
        }  
      
        cls->name = name;  
        cls->owner = owner;  
        cls->class_release = class_create_release;  
      
        retval = __class_register(cls, key);  
        if (retval)  
            goto error;  
      
        return cls;  
      
    error:  
        kfree(cls);  
        return ERR_PTR(retval);  
    }  
    EXPORT_SYMBOL_GPL(__class_create);  

    销毁函数:void class_destroy(struct class *cls)

    void class_destroy(struct class *cls)  
    {  
        if ((cls == NULL) || (IS_ERR(cls)))  
            return;  
      
        class_unregister(cls);  
    }  

    2、device_create(...) 函数

    struct device *device_create(struct class *class, struct device *parent,
                     dev_t devt, void *drvdata, const char *fmt, ...)

    功能:创建一个字符设备文件

    参数:

          struct class *class  :类
          struct device *parent:NULL
         dev_t devt  :设备号
         void *drvdata  :null、
         const char *fmt  :名字

    返回:

        struct device *

    下面是源码解析:

    struct device *device_create(struct class *class, struct device *parent,  
                     dev_t devt, void *drvdata, const char *fmt, ...)  
    {  
        va_list vargs;  
        struct device *dev;  
      
        va_start(vargs, fmt);  
        dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);  
        va_end(vargs);  
        return dev;  
    }  

    下面是一个实例:

    hello.c

    #include <linux/module.h>  
    #include <linux/fs.h>  
    #include <linux/cdev.h>  
    #include <linux/device.h>  
      
    static int major = 250;  
    static int minor=0;  
    static dev_t devno;  
    static struct class *cls;  
    static struct device *test_device;  
      
    static int hello_open (struct inode *inode, struct file *filep)  
    {  
        printk("hello_open 
    ");  
        return 0;  
    }  
    static struct file_operations hello_ops=  
    {  
        .open = hello_open,  
    };  
      
    static int hello_init(void)  
    {  
        int ret;      
        printk("hello_init 
    ");  
      
      
        devno = MKDEV(major,minor);  
        ret = register_chrdev(major,"hello",&hello_ops);  
      
        cls = class_create(THIS_MODULE, "myclass");  
        if(IS_ERR(cls))  
        {  
            unregister_chrdev(major,"hello");  
            return -EBUSY;  
        }  
        test_device = device_create(cls,NULL,devno,NULL,"hello");//mknod /dev/hello  
        if(IS_ERR(test_device))  
        {  
            class_destroy(cls);  
            unregister_chrdev(major,"hello");  
            return -EBUSY;  
        }     
        return 0;  
    }  
    static void hello_exit(void)  
    {  
        device_destroy(cls,devno);  
        class_destroy(cls);   
        unregister_chrdev(major,"hello");  
        printk("hello_exit 
    ");  
    }  
    MODULE_LICENSE("GPL");  
    module_init(hello_init);  
    module_exit(hello_exit);  

     test.c

    #include <sys/types.h>  
    #include <sys/stat.h>  
    #include <fcntl.h>  
    #include <stdio.h>  
      
      
    main()  
    {  
        int fd;  
      
      
        fd = open("/dev/hello",O_RDWR);  
        if(fd<0)  
        {  
            perror("open fail 
    ");  
            return ;  
        }  
      
      
        close(fd);  
    }  
    #ubuntu的内核源码树,如果要编译在ubuntu中安装的模块就打开这2个
    KERN_VER = $(shell uname -r)
    KERN_DIR = /lib/modules/$(KERN_VER)/build    
    
            
    # 开发板的linux内核的源码树目录
    #KERN_DIR =/lib/modules/2.6.31-14-generic/build
    #KERN_DIR = /home/book/per/kernel/linux-2.6.22.6
    #/root/driver/kernel
    
    obj-m    += hello.o
    
    all:
        make -C $(KERN_DIR) M=`pwd` modules 
    
    #cp:
    #    cp *.ko /root/porting_x210/rootfs/rootfs/driver_test
    
    .PHONY: clean    
    clean:
        make -C $(KERN_DIR) M=`pwd` modules clean
        

    转自:http://blog.csdn.net/zqixiao_09/article/details/50864014

            http://blog.csdn.net/zqixiao_09/article/details/50849735  

  • 相关阅读:
    c# 使用ajaxfileupload上传文件,通过一般处理程序(Handler)接收文件 ashx 图片 Excel文件都可以
    C#+aspx+ajaxfileupload 实现文件上传
    Java中的int与String互相转换方式
    简述 readyonly 与 disabled 的区别
    was应用服务器搭建
    MVC中贫血模型与充血模型
    npm安装教程 Vue环境搭建
    使用vs Code从0开始搭建一个vue项目(手把手教会你,包会)
    使用VS code 打开Vue项目
    Task , Thread 学习
  • 原文地址:https://www.cnblogs.com/zhaobinyouth/p/6238191.html
Copyright © 2011-2022 走看看