linux裝置驅動模型

來源:互聯網
上載者:User

最早在去年的時候學習MMC/SD/SDIO的時候就接觸過裝置驅動模型,但是當時也整天看書也是迷迷糊糊的,所以最終也沒有將這部分知識很好的整理一下。現在再次接觸到這部分知識。也算是完成一直以來的一個想法。把這部分知識簡單的整理一下備忘。

裝置驅動模型最初是為瞭解決裝置的電源管理而產生的,但是最後發展起來之後,作用就越來越大了,特別適合裝置管理。對於linux裝置驅動工程師來說,掌握裝置驅動模型非常重要。

linux的裝置驅動模型的底層機制主要包括:kobject,kobj_type,kset等幾個結構。這幾個結構定義在include/linux/kobject.h中。

kobject代表裝置驅動模型中一個基本對象。每個kobject都對應於sysfs中的一個目錄。上層結構例如device,device_driver,bus_type都嵌入了一個kobject,這相當於物件導向程式設計機制中的繼承機制。kobject的定義如下:

 60 struct kobject { 61         const char              *name;/*名稱*/ 62         struct list_head        entry;/*用於鏈入所屬的kset的鏈表*/ 63         struct kobject          *parent;/*父object*/ 64         struct kset             *kset;/*所屬kset*/ 65         struct kobj_type        *ktype;/*所屬ktype*/ 66         struct sysfs_dirent     *sd;/*sysfs中的目錄項*/ 67         struct kref             kref;/*生命週期(引用計數)管理*/ 68         unsigned int state_initialized:1;/*標記:初始化*/ 69         unsigned int state_in_sysfs:1;/*標記:在sysfs中*/ 70         unsigned int state_add_uevent_sent:1;/*標記:已發出KOBJ_ADD uevent*/ 71         unsigned int state_remove_uevent_sent:1;/*標記:已發出的KOBJ_REMOVE uevent*/ 72         unsigned int uevent_suppress:1;/*標記:禁止發出uevent*/ 73 };

kobject的基本操作:

 76 int kobject_set_name(struct kobject *kobj, const char *name, ...); 77 extern int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, 78                                   va_list vargs); 79  80 static inline const char *kobject_name(const struct kobject *kobj) 81 { 82         return kobj->name; 83 } 84  85 extern void kobject_init(struct kobject *kobj, struct kobj_type *ktype); 86 extern __printf(3, 4) __must_check 87 int kobject_add(struct kobject *kobj, struct kobject *parent, 88                 const char *fmt, ...); 89 extern __printf(4, 5) __must_check 90 int kobject_init_and_add(struct kobject *kobj, 91                          struct kobj_type *ktype, struct kobject *parent, 92                          const char *fmt, ...); 93  94 extern void kobject_del(struct kobject *kobj); 95  96 extern struct kobject * __must_check kobject_create(void); 97 extern struct kobject * __must_check kobject_create_and_add(const char *name, 98                                                 struct kobject *parent); 99 100 extern int __must_check kobject_rename(struct kobject *, const char *new_name);101 extern int __must_check kobject_move(struct kobject *, struct kobject *);102 103 extern struct kobject *kobject_get(struct kobject *kobj);104 extern void kobject_put(struct kobject *kobj);105 106 extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);

kobj_type

kobj_type是kobject所屬的類型,定義了某種類型的kobject的公用屬性和操作。定義如下:

108 struct kobj_type {109         void (*release)(struct kobject *kobj);110         const struct sysfs_ops *sysfs_ops;111         struct attribute **default_attrs;112         const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);//Callbacks so sysfs can determine namespaces113         const void *(*namespace)(struct kobject *kobj);114 };
kset
kset是一個kobject集合(或容器),包含了一系列的kobject。需要注意的是,kset內部也嵌入了kobject,這表明kset本身也是一個kobject。kset的定義如下:
159 struct kset {160         struct list_head list;161         spinlock_t list_lock;162         struct kobject kobj;163         const struct kset_uevent_ops *uevent_ops;164 };

kset的基本操作:

166 extern void kset_init(struct kset *kset);167 extern int __must_check kset_register(struct kset *kset);168 extern void kset_unregister(struct kset *kset);169 extern struct kset * __must_check kset_create_and_add(const char *name,170                                                 const struct kset_uevent_ops *u,171                                                 struct kobject *parent_kobj);172 173 static inline struct kset *to_kset(struct kobject *kobj)174 {175         return kobj ? container_of(kobj, struct kset, kobj) : NULL;176 }177 178 static inline struct kset *kset_get(struct kset *k)179 {180         return k ? to_kset(kobject_get(&k->kobj)) : NULL;181 }182 183 static inline void kset_put(struct kset *k)184 {185         kobject_put(&k->kobj);186 }187 188 static inline struct kobj_type *get_ktype(struct kobject *kobj)189 {190         return kobj->ktype;191 }
上層的資料結構
這部分就是我們比較關注的裝置,驅動和匯流排了。linux2.6之後的核心中引入了新的裝置管理機制kobject,通過這個資料結構使所有的底層都具有統一的介面,Kobject提供基本的對象管理。它與sysfs檔案系統緊密關聯,每個核心中註冊的kobject對象對應於sysfs檔案系統中的一個目錄。kobject通常通過kset組織成層次化結構,kset是具有相同類型的kobject的集合。在這些核心對象機制的基礎上,linux的裝置模型(/include/linux/device.h)包括裝置結構devices、驅動結構drivers、匯流排結構buses、裝置類結構classes幾個關鍵組件。linux中的任一裝置在裝置模型中都由一個device對象描述,其對應的資料結構struct device定義為:
633 struct device {634         struct device           *parent;635 636         struct device_private   *p;637 638         struct kobject kobj;639         const char              *init_name; /* initial name of the device */640         const struct device_type *type;641 642         struct mutex            mutex;  /* mutex to synchronize calls to643  * its driver.644  */645 646         struct bus_type *bus;           /* type of bus device is on */647         struct device_driver *driver;   /* which driver has allocated this648  device */649         void            *platform_data; /* Platform specific data, device650  core doesn't touch it */651         struct dev_pm_info      power;652         struct dev_pm_domain    *pm_domain;653 654 #ifdef CONFIG_NUMA655         int             numa_node;      /* NUMA node this device is close to */656 #endif657         u64             *dma_mask;      /* dma mask (if dma'able device) */658         u64             coherent_dma_mask;/* Like dma_mask, but for659  alloc_coherent mappings as660  not all hardware supports661  64 bit addresses for consistent662  allocations such descriptors. */663 664         struct device_dma_parameters *dma_parms;665 666         struct list_head        dma_pools;      /* dma pools (if dma'ble) */667 668         struct dma_coherent_mem *dma_mem; /* internal for coherent mem669  override */670 #ifdef CONFIG_CMA671         struct cma *cma_area;           /* contiguous memory area for dma672  allocations */673 #endif674         /* arch specific additions */675         struct dev_archdata     archdata;676 677         struct device_node      *of_node; /* associated device tree node */678 679         dev_t                   devt;   /* dev_t, creates the sysfs "dev" */680         u32                     id;     /* device instance */681 682         spinlock_t              devres_lock;683         struct list_head        devres_head;684 685         struct klist_node       knode_class;686         struct class            *class;/*所屬的類別*/687         const struct attribute_group **groups;  /* optional groups */688 689         void    (*release)(struct device *dev);690 };

device的基本操作

788 extern int __must_check device_register(struct device *dev);789 extern void device_unregister(struct device *dev);790 extern void device_initialize(struct device *dev);791 extern int __must_check device_add(struct device *dev);792 extern void device_del(struct device *dev);793 extern int device_for_each_child(struct device *dev, void *data,794                      int (*fn)(struct device *dev, void *data));795 extern struct device *device_find_child(struct device *dev, void *data,796                                 int (*match)(struct device *dev, void *data));

device_driver

device_driver代表一個裝置驅動程式,對應於/sys/bus/xxx/drivers./下的一個目錄。定義如下:

215 struct device_driver {216         const char              *name;/*名稱*/217         struct bus_type         *bus;/*匯流排*/218 219         struct module           *owner;/*所有者*/220         const char              *mod_name;      /* used for built-in modules */221 222         bool suppress_bind_attrs;       /* disables bind/unbind via sysfs */223 224         const struct of_device_id       *of_match_table;225         /*操作裝置的方法*/226         int (*probe) (struct device *dev);227         int (*remove) (struct device *dev);228         void (*shutdown) (struct device *dev);229         int (*suspend) (struct device *dev, pm_message_t state);230         int (*resume) (struct device *dev);231         const struct attribute_group **groups;/*屬性群組*/232 233         const struct dev_pm_ops *pm;/*電源管理*/234 235         struct driver_private *p;236 };

bus_type

bus_type代表一個匯流排,對應於/sys/bus/下的一個目錄。定義如下:

 90 struct bus_type { 91         const char              *name; 92         const char              *dev_name; 93         struct device           *dev_root; 94         struct bus_attribute    *bus_attrs;/*匯流排屬性*/ 95         struct device_attribute *dev_attrs;/*裝置預設屬性*/ 96         struct driver_attribute *drv_attrs;/*驅動預設屬性*/ 97         /*對裝置和驅動的操作方法*/ 98         int (*match)(struct device *dev, struct device_driver *drv); 99         int (*uevent)(struct device *dev, struct kobj_uevent_env *env);100         int (*probe)(struct device *dev);101         int (*remove)(struct device *dev);102         void (*shutdown)(struct device *dev);103 104         int (*suspend)(struct device *dev, pm_message_t state);105         int (*resume)(struct device *dev);106 107         const struct dev_pm_ops *pm;108 109         struct iommu_ops *iommu_ops;110 111         struct subsys_private *p;112 };
match()方法用於判斷掛在匯流排下的某個device和某個device_driver是否匹配,在一個device或一個device_driver註冊到匯流排上時調用。uevent()方法用於為uevent機制添加環境變數,在處理uevent時被調用。其他方法都是操作匯流排上掛接的device的。probe(),remove().shutdown(),resume()這幾個方法在device_driver中也定義了。核心在調用這些方法時,會優先調用bus_type中定義的方法。如果相應的方法在bus_type中未定義,才會調用device_driver中定義的方法。bus_type的基本操作:
122 extern int __must_check bus_register(struct bus_type *bus);123 extern void bus_unregister(struct bus_type *bus);124 125 extern int __must_check bus_rescan_devices(struct bus_type *bus);126 127 /* iterator helpers for buses */128 struct subsys_dev_iter {129         struct klist_iter               ki;130         const struct device_type        *type;131 };132 void subsys_dev_iter_init(struct subsys_dev_iter *iter,133                          struct bus_type *subsys,134                          struct device *start,135                          const struct device_type *type);136 struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);137 void subsys_dev_iter_exit(struct subsys_dev_iter *iter);138 139 int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,140                      int (*fn)(struct device *dev, void *data));141 struct device *bus_find_device(struct bus_type *bus, struct device *start,142                                void *data,143                                int (*match)(struct device *dev, void *data));144 struct device *bus_find_device_by_name(struct bus_type *bus,145                                        struct device *start,146                                        const char *name);147 struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id,148                                         struct device *hint);149 int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,150                      void *data, int (*fn)(struct device_driver *, void *));

bus_type、device和device_driver之間的關係

bus_type相當於一個容器,是device和device_driver的管理機構,它包含了一個device集合(kset)和一個device_driver集合(kset),分別表示掛在匯流排下的所有裝置和所有裝置驅動程式。
device_driver掛在某個bus_type下面,包含了一個device集合(kset),表示這個驅動程式操作(或控制)的所有裝置。device_driver還包含了一個bus_type指標,表示驅動程式所在的匯流排。
device掛在某個bus_type下面,包含了一個device_driver指標,表示這個裝置對應的裝置驅動程式。device還包含一個bus_type指標,表示裝置所在的匯流排。
需要說明的是,一個實際的匯流排在裝置驅動模型中是用兩個結構表示的:bus_type和device。bus_type代表匯流排類型,出現在/sys/bus/目錄下;device代表匯流排裝置,出現在/sys/devices/目錄下,這表明實際的匯流排本質上是一種裝置。

/**
 * bus_register - register a bus with the system.
 * @bus: bus.
 *
 * Once we have that, we registered the bus with the kobject
 * infrastructure, then register the children subsystems it has:
 * the devices and drivers that belong to the bus.
 */
int bus_register(struct bus_type *bus)
{
int retval;
struct subsys_private *priv;

priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;

priv->bus = bus;
bus->p = priv;

BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.