日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

The Linux device model

發(fā)布時(shí)間:2024/4/17 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 The Linux device model 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

/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)文件。

struct kobject {const char * k_name;char name[KOBJ_NAME_LEN];struct kref kref;struct list_head entry;struct kobject * parent;struct kset * kset;struct kobj_type * ktype;struct sysfs_dirent * sd;wait_queue_head_t poll; };

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_IWUSR

2、方法(operations)
想一想在文件系統(tǒng)上能干什么呢?無(wú)非是創(chuàng)建文件夾(kobject),創(chuàng)建文件(屬性)。

// kobject初始化函數(shù)void kobject_init(struct kobject * kobj);// 設(shè)置指定kobject的名稱int kobject_set_name(struct kobject *kobj, const char *format, ...);// 將kobj 對(duì)象的引用計(jì)數(shù)加,同一時(shí)候返回該對(duì)象的指針struct kobject *kobject_get(struct kobject *kobj);// 將kobj對(duì)象的引用計(jì)數(shù)減,假設(shè)引用計(jì)數(shù)降為。則調(diào)用kobject release()釋放該kobject對(duì)象void kobject_put(struct kobject * kobj);// 將kobj對(duì)象添加Linux設(shè)備層次。

掛接該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)建屬性

struct device_attribute { struct attribute attr; ssize_t (*show)(struct device *dev, char *buf); ssize_t (*store)(struct device *dev, const char *buf, size_t count); };

這些屬性結(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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。