The Linux device model
/sys和 /dev的疑問(wèn)
1、/dev 下放的是設(shè)備文件,是由應(yīng)用層mknod創(chuàng)建的文件。假設(shè)底層驅(qū)動(dòng)對(duì)mknod的設(shè)備號(hào)有相應(yīng)的驅(qū)動(dòng),如open等函數(shù)。那么應(yīng)用層open “/dev/**”時(shí),就會(huì)調(diào)用究竟層的驅(qū)動(dòng)。說(shuō)白了,/dev下放的是內(nèi)核和應(yīng)用層交互的文件,讓應(yīng)用層去open,write,poll等。
2、/sys 是個(gè)文件系統(tǒng),你寫內(nèi)核代碼時(shí),假設(shè)有調(diào)用kobj_init等函數(shù),就會(huì)在/sys下的相應(yīng)文件夾生成相應(yīng)文件。 它的作用是將內(nèi)核注冊(cè)的設(shè)備、驅(qū)動(dòng)、BUS連成一個(gè)樹形結(jié)構(gòu)。
另外,應(yīng)用層也能夠通過(guò)讀寫/sys下的文件和內(nèi)核進(jìn)行交互(ktype)。 說(shuō)白了/sys就是一個(gè)樹形結(jié)構(gòu)。讓你明確內(nèi)核都有哪些驅(qū)動(dòng)和設(shè)備已經(jīng)bus。方便電源管理。
3、http://blog.csdn.net/eliot_shao/article/details/13019389
在篇博客里《圖解linux設(shè)備模型》中,對(duì)udev和sysfs的關(guān)系做了更具體的說(shuō)明。
sysfs底層操作
1、kobject結(jié)構(gòu)
一提到kobject非常多人就不想看了。千篇一律。可是使用這個(gè)結(jié)構(gòu),我們能夠建立設(shè)備驅(qū)動(dòng)模型,所以必須明確。開發(fā)驅(qū)動(dòng)程序?qū)ξ襾?lái)說(shuō),也就是建幾個(gè)文件夾,創(chuàng)幾個(gè)屬性文件。內(nèi)核的設(shè)備驅(qū)動(dòng)架構(gòu)已經(jīng)打好了,調(diào)幾個(gè)函數(shù)來(lái)用就能夠了。在sysfs文件系統(tǒng)里,kobject相應(yīng)文件夾。屬性(attribute)相應(yīng)文件。
kobject內(nèi)容包括文件夾的名字。parent上層文件夾,假設(shè)parent=NULL就在/sys以下創(chuàng)建文件夾。ktype可理解為這個(gè)文件夾的屬性。
struct kobj_type {void (*release)(struct kobject *);struct sysfs_ops * sysfs_ops;struct attribute ** default_attrs; }; struct sysfs_ops {ssize_t (*show)(struct kobject *, struct attribute *,char *);//讀方法ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);//寫方法 }; struct attribute {const char * name;struct module * owner;mode_t mode; };//屬性文件的名字。模式,僅僅讀設(shè)為S_IRUGO,可寫設(shè)為S_IWUSR2、方法(operations)
想一想在文件系統(tǒng)上能干什么呢?無(wú)非是創(chuàng)建文件夾(kobject),創(chuàng)建文件(屬性)。
掛接該kobject對(duì)象到kset的list鏈中,添加父文件夾各級(jí)kobject的引// 用計(jì)數(shù),在其parent指向的文件夾下創(chuàng)建文件節(jié)點(diǎn),并啟動(dòng)該類型內(nèi)核對(duì)象的hotplug函數(shù)
int kobject_add(struct kobject * kobj); // kobject注冊(cè)函數(shù),調(diào)用kobject init()初始化kobj,再調(diào)用kobject_add()完畢該內(nèi)核對(duì)象的注冊(cè) int kobject_register(struct kobject * kobj); // 從Linux設(shè)備層次(hierarchy)中刪除kobj對(duì)象 void kobject_del(struct kobject * kobj); // kobject注銷函數(shù). 與kobject register()相反。它首先調(diào)用kobject del從設(shè)備層次中刪除該對(duì)象。再調(diào)// 用kobject put()降低該對(duì)象的引用計(jì)數(shù),假設(shè)引用計(jì)數(shù)降為,則釋放kobject對(duì)象 void kobject_unregister(struct kobject * kobj);設(shè)備模型上層容器
這里說(shuō)的上層容器指的是總線類型(bus_type)、設(shè)備(device)和驅(qū)動(dòng)(device_driver)。LDD3里面舉過(guò)一個(gè)例如。把kobject當(dāng)成一個(gè)基類,總線類型、設(shè)備、驅(qū)動(dòng)和kobject都是繼承關(guān)系。這些上層的容器自然具備了sysfs的操作方法!
總線類型一般不須要我們創(chuàng)建了。內(nèi)核支持大多數(shù)總線類型(pci。usb,iic…),還包括了虛擬總線類型(platform_bus),所以這里就不涉及怎樣創(chuàng)建總線,怎樣建立總線的屬性文件云云。
1. 設(shè)備 device
設(shè)備的操作可簡(jiǎn)單理解為1、注冊(cè)設(shè)備;2、創(chuàng)建設(shè)備屬性文件。
通常的注冊(cè)和注銷函數(shù):
int device_register(struct device *dev);
void device_unregister(struct device *dev);
設(shè)備的注冊(cè)和注銷包括了對(duì)底層的sysfs的操作。諸如kobject_init。kobject_add…
創(chuàng)建屬性
這些屬性結(jié)構(gòu)可在編譯時(shí)建立, 使用這些宏:
DEVICE_ATTR(name, mode, show, store);
結(jié)果結(jié)構(gòu)通過(guò)前綴 dev_attr_ 到給定名子上來(lái)命名. 屬性文件的實(shí)際管理使用通常的函數(shù)對(duì)來(lái)處理:
int device_create_file(struct device *device, struct device_attribute *entry);
void device_remove_file(struct device *dev, struct device_attribute *attr);
2. 驅(qū)動(dòng) driver
驅(qū)動(dòng)的操作可簡(jiǎn)單理解為1、注冊(cè)驅(qū)動(dòng);2、創(chuàng)建驅(qū)動(dòng)屬性文件。
通常的注冊(cè)和注銷函數(shù):
int driver_register(struct device_driver *drv);
void driver_unregister(struct device_driver *drv);
設(shè)備的注冊(cè)和注銷包括了對(duì)底層的sysfs的操作,諸如kobject_init,kobject_add…
創(chuàng)建屬性
DRIVER_ATTR(name, mode, show, store);
int driver_create_file(struct device_driver *drv, struct driver_attribute *attr);
void driver_remove_file(struct device_driver *drv, struct driver_attribute *attr);
摘一段驅(qū)動(dòng)代碼來(lái)講講
#include <linux/fs.h> #include <asm/uaccess.h> #include <linux/pci.h> #include <linux/input.h> #include <linux/platform_device.h>struct input_dev *vms_input_dev; /* Representation of an input device */ static struct platform_device *vms_dev; /* Device structure *//* Sysfs method to input simulatedcoordinates to the virtualmouse driver */ static ssize_t write_vms(struct device *dev,struct device_attribute *attr,const char *buffer, size_t count) {int x,y;sscanf(buffer, "%d%d", &x, &y);/* Report relative coordinates via theevent interface */input_report_rel(vms_input_dev, REL_X, x);input_report_rel(vms_input_dev, REL_Y, y);input_sync(vms_input_dev);return count; } /* Attach the sysfs write method */ DEVICE_ATTR(coordinates, 0644, NULL, write_vms); /* Attribute Descriptor */ static struct attribute *vms_attrs[] = {&dev_attr_coordinates.attr,NULL }; /* Attribute group */ static struct attribute_group vms_attr_group = {.attrs = vms_attrs, }; /* Driver Initialization */ int __init vms_init(void) {/* Register a platform device */vms_dev = platform_device_register_simple("vms", -1, NULL, 0);if (IS_ERR(vms_dev)) {PTR_ERR(vms_dev);printk("vms_init: error\n");}/* Create a sysfs node to read simulated coordinates */sysfs_create_group(&vms_dev->dev.kobj, &vms_attr_group);/* Allocate an input device data structure */vms_input_dev = input_allocate_device();if (!vms_input_dev) {printk("Bad input_alloc_device()\n");}/* Announce that the virtual mouse will generaterelative coordinates */set_bit(EV_REL, vms_input_dev->evbit);set_bit(REL_X, vms_input_dev->relbit);set_bit(REL_Y, vms_input_dev->relbit);/* Register with the input subsystem */input_register_device(vms_input_dev);printk("Virtual Mouse Driver Initialized.\n");return 0; } /* Driver Exit */ void vms_cleanup(void) {/* Unregister from the input subsystem */input_unregister_device(vms_input_dev);/* Cleanup sysfs node */sysfs_remove_group(&vms_dev->dev.kobj, &vms_attr_group);/* Unregister driver */platform_device_unregister(vms_dev);return; }module_init(vms_init); module_exit(vms_cleanup);這是從《Essential Linux Device Drivers》第七章輸入設(shè)備摘的代碼,實(shí)現(xiàn)從虛擬鼠標(biāo)讀取數(shù)據(jù)坐標(biāo)上報(bào)的功能。
這里使用了總線platform_bus。
vms_dev = platform_device_register_simple(“vms”, -1, NULL, 0);注冊(cè)設(shè)備到總線;
sysfs_create_group(&vms_dev->dev.kobj, &vms_attr_group);創(chuàng)建屬性文件。在linux/sysfs.h中引用,相似于sysfs_create_file。
input_register_device(vms_input_dev);注冊(cè)設(shè)備文件到input子系統(tǒng),具體細(xì)節(jié)參考源代碼;
總的來(lái)說(shuō),就是干了兩件事,創(chuàng)建文件夾對(duì)象和創(chuàng)建屬性,然后加到設(shè)備模型中。建立一個(gè)資源管理樹!
文章僅僅是片面的。宏觀的略談驅(qū)動(dòng)模型。經(jīng)驗(yàn)不足,僅作參考!
參考資料
http://bbs.csdn.net/topics/380166008
http://blog.csdn.net/xiahouzuoxin/article/details/8943863
轉(zhuǎn)載于:https://www.cnblogs.com/blfshiye/p/5136307.html
總結(jié)
以上是生活随笔為你收集整理的The Linux device model的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MetadataType的使用
- 下一篇: Linux内核总结