• 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表示了一条总线拥有两条链表,一条是设备链表,一条是驱动链表。我们知道了总线对应的数据结构,就可以找到这条总线关联了多少设备,又有哪些驱动来支持这类设备。






  • 相关阅读:
    UWP开发之Mvvmlight实践一:如何在项目中添加使用Mvvmlight(图文详解)
    poj2909 欧拉素数筛选
    南京区域赛总结
    poj 2551 Ones
    poj 2524 Ubiquitous Religions(简单并查集)
    poj 2503 Babelfish(字典树或map或哈希或排序二分)
    poj 3080 Blue Jeans
    hdoj 4762 Cut the Cake
    linux tar.gz zip 解压缩 压缩命令
    poj 3714 寻找最近点对
  • 原文地址:https://www.cnblogs.com/pangblog/p/3395487.html
Copyright © 2020-2023  润新知