/************************************************************************************html
*本文爲我的學習記錄,若有錯誤,歡迎指正。node
* http://www.cnblogs.com/chen-farsight/p/6154941.html網絡
* http://www.javashuo.com/article/p-krtbudse-m.html數據結構
************************************************************************************/函數
(1)手動建立:mknod命令學習
在驅動程序insmod成功以後,經過mknod命令手動建立設備文件至/dev目錄下:mknod /dev/xxx c 主設備號 次設備號。("c"表示字符設備、"b"表示塊設備、"p"表示網絡設備)spa
(2)自動建立設備文件:mdev.net
在設備驅動註冊到系統後,調用class_create爲該設備在/sys/class目錄下建立一個設備類,再調用device_create函數爲每一個設備建立對應的設備,並經過uevent機制調用mdev(嵌入式linux由busybox提供)來調用mknod建立設備文件至/dev目錄下。指針
struct class和struct device則經過sysfs向用戶層提供信息。
class_private是class的私有結構,class經過class_private註冊到系統中;device_private是device的私有結構,device經過device_private註冊到系統中。註冊到系統中也是將相應的數據結構加入到系統已經存在的鏈表中,可是這些連接的細節並不但願暴露給用戶,也沒有必要暴露出來,因此纔有private的結構。
//所在文件/kernel/include/linux/device.h //設備類 struct class { const char *name; //設備類名稱 struct module *owner;//建立設備類的module struct class_attribute *class_attrs;//設備類屬性 struct device_attribute *dev_attrs;//設備屬性 struct kobject *dev_kobj;//kobject再sysfs中表明一個目錄 ..................... struct class_private *p;//設備類得以註冊到系統的鏈接件 }; //drivers/base/base.h struct class_private { struct klist class_devices;//設備類包含的設備(kobject) .................................. struct class *class;//指向設備類數據結構,即要建立的本級目錄信息 };
//所在文件/kernel/include/linux/device.h struct device { struct device *parent; //sysfs/devices/中的父設備 struct device_private *p; //設備得以註冊到系統的鏈接件 struct kobject kobj; //設備目錄 const char *init_name; //設備名稱 struct bus_type *bus; //設備所屬總線 struct device_driver *driver; //設備使用的驅動 struct klist_node knode_class;//鏈接到設備類的klist struct class *class; //所屬設備類 ..................... }; //所在文件/kernel/drivers/base/base.h struct device_private { struct klist klist_children; //鏈接子設備 struct klist_node knode_parent; //加入到父設備鏈表 struct klist_node knode_driver; //加入到驅動的設備鏈表 struct klist_node knode_bus; //加入到總線的鏈表 struct device *device; //對應設備結構 };
step1:調用class_create函數在/sys/class目錄下建立一個設備類。
/* 功能:在/sys/class目錄下建立一個目錄,目錄名是name指定的 參數: struct module *owner - THIS_MODULE const char *name - 設備名 返回值: 成功:class指針 失敗: - bool IS_ERR(const void *ptr) 判斷是否出錯 long PTR_ERR(const void *ptr) 轉換錯誤碼 */ struct class *class_create(struct module *owner, const char *name);
step2:調用device_create函數在step1建立的設備類目錄下建立具體的設備目錄和設備屬性文件。
/* 功能: 在class指針指向的目錄下再建立一個目錄,目錄名由const char *fmt, ...指出、並導出設備信息(dev_t) 參數: struct class *cls - class指針 struct device *parent - 父對象,NULL dev_t devt - 設備號 void *drvdata - 驅動私有數據 const char *fmt, ... - fmt是目錄名字符串格式,...就是不定參數 返回值: 成功 - device指針 失敗 - bool IS_ERR(const void *ptr) 判斷是否出錯 long PTR_ERR(const void *ptr) 轉換錯誤碼 */ struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
step3:在/dev建立設備文件(系統自動進行)
step一、step2都是在sysfs文件系統中建立目錄或者文件,而應用程序訪問的設備文件則須要建立在/dev/目錄下。該項工做由mdev完成(需保證根文件系統支持mdev,由busybox配置)。
step1:刪除設備類目錄下的設備
/* 功能:刪除device_create建立的目錄 參數: struct class *cls - class指針 dev_t devt - 設備號 */ void device_destroy(struct class *cls, dev_t devt);
step2:刪除/sys/class目錄下的設備類
/* 功能:刪除class指針指向的目錄 參數: struct class *cls - class指針 */ void class_destroy(struct class *cls);