如何自動創建設備節點


創建設備文件的方法:

第一種是使用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 \n");  
    return 0;  
}  
static struct file_operations hello_ops=  
{  
    .open = hello_open,  
};  
  
static int hello_init(void)  
{  
    int ret;      
    printk("hello_init \n");  
  
  
    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 \n");  
}  
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 \n");  
        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  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM