Linux驅動之裝置模型(4)-匯流排

來源:互聯網
上載者:User

1 匯流排

   匯流排,是處理器與一個或者多個裝置之間的通道。在Linux裝置模型中,所有的裝置都通過匯流排相連,甚至是那些內部的虛擬"platform"匯流排。用bus_type結構來描述。

   struct bus_type {const char*name;         /* 匯流排名 */const char*dev_name;    struct device*dev_root;struct bus_attribute*bus_attrs;  /* 匯流排屬性 */struct device_attribute*dev_attrs;   /* 裝置屬性 */struct driver_attribute*drv_attrs;    /* 驅動屬性 */   /* 當向該匯流排註冊裝置或匯流排調用,用於裝置與驅動的匹配 */int (*match)(struct device *dev, struct device_driver *drv);   /* 當添加或移除裝置時,調用此函數向使用者空間產生環境變數 */int (*uevent)(struct device *dev, struct kobj_uevent_env *env);   /* 當裝置與驅動匹配上時調用,初始化匹配裝置 */int (*probe)(struct device *dev);   /* 當裝置移除時調用 */int (*remove)(struct device *dev);void (*shutdown)(struct device *dev);   /* 匯流排的電源管理操作 */int (*suspend)(struct device *dev, pm_message_t state);int (*resume)(struct device *dev);   /* 裝置、驅動的電源管理操作集 */const struct dev_pm_ops *pm;struct iommu_ops *iommu_ops;   /* 私人資料指標,這個比較重要的一個成員 */struct subsys_private *p;}; 

2. 匯流排聲明

     核心中的每一種匯流排類型(PCI,I2C,USB,etc)都用bus_type結構體來描述,需要初始化相應的name成員和match函數。

      struct bus_type pci_bus_type = {       .name    = "pci",       .match   = pci_bus_match,      };

3. 註冊和登出函數

     int bus_register(struct bus_type *bus);

     void bus_unregister(struct bus_type *bus);

    匯流排 註冊函數分析

int bus_register(struct bus_type *bus){         retval =kobject_set_name(&priv->subsys.kobj, "%s", bus->name);          priv->subsys.kobj.kset = bus_kset;         priv->subsys.kobj.ktype =&bus_ktype;         priv->drivers_autoprobe = 1;          /* 註冊bus kset,在bus/下產生bus->name目錄 */         retval = kset_register(&priv->subsys);          retval = bus_create_file(bus,&bus_attr_uevent);          /* 產生device目錄 */         priv->devices_kset =kset_create_and_add("devices", NULL,                                                         &priv->subsys.kobj);          /* 產生driver目錄 */         priv->drivers_kset =kset_create_and_add("drivers", NULL,                                                         &priv->subsys.kobj);          /* 初始化裝置鏈和驅動鏈 */         klist_init(&priv->klist_devices,klist_devices_get, klist_devices_put);         klist_init(&priv->klist_drivers,NULL, NULL);          retval = add_probe_files(bus);          retval = bus_add_attrs(bus);}

Klist_drivers和klist_devices這兩條鏈非常重要,用來遍曆drivers_kset和devices_kset,drivers_kset和devices_kset分別是匯流排上所有driver和device的集合。

4. match() 函數

    match函數為匯流排提供了檢測驅動是否支援此裝置的功能,通過device IDs來進行匹配。當驅動被註冊到匯流排上,匯流排上的裝置鏈表會被遍曆,match()被調用來完成對每個裝置的匹配。

5. subsys_private

    subsys_private是一個比較重要的成員。

    struct subsys_private {struct kset subsys;struct kset *devices_kset;      /* 裝置集,包含匯流排上所有的裝置 */struct list_head interfaces;struct mutex mutex;struct kset *drivers_kset;  /* 驅動集,包含匯流排所有的驅動 */struct klist klist_devices;  /* 裝置鏈表,串連匯流排上所有的裝置 */struct klist klist_drivers;    /* 驅動鏈表,串連匯流排上所有的驅動 */struct blocking_notifier_head bus_notifier;unsigned int drivers_autoprobe:1;struct bus_type *bus;       /* 指回bus_type */struct kset glue_dirs;struct class *class;};

裝置鏈表和驅動鏈表串連了註冊到匯流排上的所有裝置和驅動,經常用來遍曆和查詢匯流排上的裝置和驅動。裝置模型核心層提供了兩個API,用來遍曆裝置和驅動。

int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,                     int (*fn)(struct device *, void *));int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,                     void * data, int (*fn)(struct device_driver *, void *));

6. 匯出屬性,匯流排的屬性用bus_attribute來描述

struct bus_attribute {        struct attribute        attr;      /* 屬性 */        ssize_t (*show)(struct bus_type *, char * buf);    /* 讀屬性方法 */        ssize_t (*store)(struct bus_type *, const char * buf, size_t count);  /* 寫屬性方法 */};

BUS_ATTR宏可以在編譯時間刻建立和初始化bus_attribute結構體

BUS_ATTR(_name, _mode, _show, _store)

在LDM裡提供了兩個介面用來在sysfs目錄下產生和移除屬性檔案

int bus_create_file(struct bus_type *, struct bus_attribute *);void bus_remove_file(struct bus_type *, struct bus_attribute *);

7. 執行個體分析

建立一條scbus匯流排,並添加版本屬性。實際中我們並不需要自己建立匯流排,此實驗僅用來學習

/** for learn bus*/#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/device.h> static char *Version = "revision 1.0,scbus"; /* 匹配函數,通過裝置名稱和驅動名來匹配 */static int scbus_match(struct device *dev,struct device_driver *driver){         printk("\n%s,%s\n", dev_name(dev), driver->name);         return!strncmp(dev_name(dev), driver->name, strlen(driver->name));} static void scbus_release(struct device*dev){         printk("scbusrelease\n");} struct bus_type scbus_type = {         .name       = "scbus",         .match   = scbus_match,};EXPORT_SYMBOL_GPL(scbus_type); struct device scbus = {         .init_name        = "scbus0",         .release   = scbus_release,};EXPORT_SYMBOL_GPL(scbus); /** export bus attribute*/static ssize_t show_bus_version(structbus_type *bus, char *buf){         returnsnprintf(buf, PAGE_SIZE, "%s\n", Version);}static BUS_ATTR(version, S_IRUGO,show_bus_version, NULL); static int __init scbus_init(void){         intret;          ret= bus_register(&scbus_type);         if(ret)                   returnret;          ret= bus_create_file(&scbus_type, &bus_attr_version);         if(ret)                   gotocreate_error;          ret= device_register(&scbus);         if(ret)                   gotodevice_error;          printk("Createa scbus\n");         return0; device_error:         bus_remove_file(&scbus_type,&bus_attr_version);create_error:         bus_unregister(&scbus_type);         returnret;} static void __exit scbus_exit(void){         device_unregister(&scbus);         bus_remove_file(&scbus_type,&bus_attr_version);         bus_unregister(&scbus_type);         printk("Removea scbus\n");} module_init(scbus_init);module_exit(scbus_exit); MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("CJOK<cjok.liao@gmail.com>");

實驗結果:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.