当前位置: 首页 > news >正文

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






 

相关文章:

  • 安装db2 提示不是有效的win32应用程序?
  • 建站须知
  • Java中如何实现类似C++结构体的二级排序
  • 防暴力破解 Fail2Ban之python
  • JMETER 2.10的安装
  • 缓存 - 运行时内存缓存
  • lvs群集-nat模型
  • 原创D3D几何实例化的DEMO
  • 将 Shiro 作为应用的权限基础 四:shiro的配置说明
  • 理解NAT的地址类型
  • centos 6.5安装vncserver 并开启远程桌面
  • 词性标注-隐马尔科夫模型应用
  • jquery,php之间的ajax关系以及json
  • 使用jQuery.form插件,实现完美的表单异步提交
  • UIDynamic(物理仿真)
  • Android单元测试 - 几个重要问题
  • AWS实战 - 利用IAM对S3做访问控制
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • FastReport在线报表设计器工作原理
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • java第三方包学习之lombok
  • nodejs:开发并发布一个nodejs包
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • Redis 懒删除(lazy free)简史
  • use Google search engine
  • Vue官网教程学习过程中值得记录的一些事情
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 开发基于以太坊智能合约的DApp
  • 数据仓库的几种建模方法
  • 思维导图—你不知道的JavaScript中卷
  • 应用生命周期终极 DevOps 工具包
  • 用element的upload组件实现多图片上传和压缩
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • #QT(智能家居界面-界面切换)
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (全注解开发)学习Spring-MVC的第三天
  • (三)elasticsearch 源码之启动流程分析
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ./configure,make,make install的作用(转)
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .net framework profiles /.net framework 配置
  • .NET/C# 推荐一个我设计的缓存类型(适合缓存反射等耗性能的操作,附用法)
  • .NET命令行(CLI)常用命令
  • .NET学习全景图
  • @Pointcut 使用
  • [ SNOI 2013 ] Quare
  • [1159]adb判断手机屏幕状态并点亮屏幕
  • [Angularjs]asp.net mvc+angularjs+web api单页应用
  • [BZOJ 4034][HAOI2015]T2 [树链剖分]
  • [C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改
  • [c]统计数字
  • [CSS]文字旁边的竖线以及布局知识