閱讀885 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Linux內核--usb子係統的分析

drivers/usb/core/usb.c

subsys_init(usb_init);
module_exit(usb_exit);

我們 看到一個subsys_initcall,它也是一個宏,我們可以把它理解為module_init,隻不過這部分代碼比較核心,開發者們把它看做一個子係統,而不僅僅是一個模塊。usbcore這個模塊它代表的不是某一個設備,而是所有usb設備賴以生存的模塊,Linux中,像這樣一個類別的設備驅動被鬼節為一個子係統。比如PCI子係統、SCSI子係統,基本上,drivers/目錄西麵的每一個目錄就算為一個子係統,因為他們代表了一類設備。

subsys_initcall(usb_init)的意思就是告訴我們usb_init是usb子係統真正的初始化函數,而usb_exit()將是整個usb子係統的結束時的清理函數。

我們需要從usb_init函數開始分析:

static int __init usb_init(void)

__init標記:它對於內核來說就是一種暗示,表明這個函數僅僅在初始化期間使用,在模塊被裝載之後,它占用的資源就會釋放掉,用作別用。__init的定義在include/linux/init.h

#define __init__section(.init.text) __cold notrace

__attribute__、__section__等等都是GNUC的擴展,GNUC作為能夠編譯內核的唯一編譯器。通常編譯器將函數放在.text段,變量放在.data或.bss段,使用section屬性,可以讓編譯器將函數或變量放在指定的段中。__init的定義便表示將它修飾的代碼放在.init.text段中。連接器可以把相同段的代碼或數據安排在一起,比如__init修飾的所有代碼都被放在.init.text段中,初始化結束後就可以釋放這部分內存。


設備模型:

總線、設備、驅動:(bus、device、driver)定義在include/linux/device.h

struct bus_type {
	const char		*name;
	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);

	struct dev_pm_ops *pm;

	struct bus_type_private *p;
};

struct device_driver {
	const char		*name;
	struct bus_type		*bus;

	struct module		*owner;
	const char 		*mod_name;	/* used for built-in modules */

	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);
	struct attribute_group **groups;

	struct dev_pm_ops *pm;

	struct driver_private *p;
};

struct device {
	struct device		*parent;

	struct device_private	*p;

	struct kobject kobj;
	const char		*init_name; /* initial name of the device */
	struct device_type	*type;

	struct semaphore	sem;	/* semaphore to synchronize calls to
					 * its driver.
					 */

	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this
					   device */
	void		*driver_data;	/* data private to the driver */
	void		*platform_data;	/* Platform specific data, device
					   core doesn't touch it */
	struct dev_pm_info	power;

#ifdef CONFIG_NUMA
	int		numa_node;	/* NUMA node this device is close to */
#endif
	u64		*dma_mask;	/* dma mask (if dma'able device) */
	u64		coherent_dma_mask;/* Like dma_mask, but for
					     alloc_coherent mappings as
					     not all hardware supports
					     64 bit addresses for consistent
					     allocations such descriptors. */

	struct device_dma_parameters *dma_parms;

	struct list_head	dma_pools;	/* dma pools (if dma'ble) */

	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
					     override */
	/* arch specific additions */
	struct dev_archdata	archdata;

	dev_t			devt;	/* dev_t, creates the sysfs "dev" */

	spinlock_t		devres_lock;
	struct list_head	devres_head;

	struct klist_node	knode_class;
	struct class		*class;
	struct attribute_group	**groups;	/* optional groups */

	void	(*release)(struct device *dev);
};

struct device中的bus表示這個設備連到那個總線上,driver表示這個設備的驅動是什麼,struct device_driver中的bus表示這個驅動屬於那個總線,klist_devices表示這個驅動都支持哪些設備,因為這裏device是複數,又是list,更因為一個驅動可以支持多個設備,而一個設備隻能綁定一個驅動。當然struct bus_type中的drivers和devices分別表示了這個總線擁有哪些設備和哪些驅動。

kobjece和kset是Linux設備模型中最基本的元素,存在的意義是把總線、設備和驅動這樣的對象連接到設備模型上。

整個linux的設備模型是一個OO的體係結構,總線、設備和驅動都是其對象,kobject是它們的基類,所實現的知識一些公共的接口,kset是同種類型kobject對象的集合,也可以說是對象的容器。因為在c裏不可能有c++裏的class繼承、組合等概念,隻有通過kobject嵌入到對象結構裏來實現。這樣,內核使用kobject將各個對象連接起來組成一個分層的結構體係。kobject結構裏包含了parent成員,指向了另外一個kobject結構,也就是這個分層結構的上一層結點。而kset是通過鏈表來實現的,struct bus_type結構中的成員drivers和devices表示了一條總線擁有兩條鏈表,一條是設備鏈表,一條是驅動鏈表。我們知道了總線對應的數據結構,就可以找到這條總線關聯了多少設備,又有哪些驅動來支持這類設備。






最後更新:2017-04-03 14:53:53

  上一篇:go Java IO--字節流與字符流OutputStream/InputStream/Writer/Reader
  下一篇:go HTTP協議返回狀態碼大全