Linux设备驱动编程模型之设备篇

本文深入探讨Linux设备驱动编程模型,涉及数据结构如设备表述符、Bus描述符等,以及内核启动时设备驱动的初始化过程,包括sysfs目录结构的生成。文章通过源码分析解释了设备、总线、类的初始化,展示了设备与驱动、设备与总线的关联方式,为理解Linux设备驱动提供了全面的视角。
摘要由CSDN通过智能技术生成
  设备驱动程序模型建立在几个基本数据结构上,这些结构描述了总线、设备、设备驱动、属性以及他们之间的关系。我们首先认识一下这些数据结构。  

一、数据结构

设备表述符

struct device {
	struct device		*parent;/*指向父设备的指针*/
	/*该字段用于管理device和其他device结构,一起device
	与其他结构之间的关系*/
	struct device_private	*p;

	struct kobject kobj;/*内嵌的kobject结构*/
	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		*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缓冲池链表的首部*//* dma pools (if dma'ble) */

	struct dma_coherent_mem	*dma_mem;/*指向设备所使用的一致性DMA存储器描述符的指针*//* 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;
	const struct attribute_group **groups;	/* optional groups */

	void	(*release)(struct device *dev);/*释放设备描述符的回调函数*/
};

Bus描述符

struct bus_type {
	const char		*name;/*总线类型名称*/
	/*指向对象的指针,该对象包含总线属性和用于导出此属性到sysfs文件系统的方法*/
	struct bus_attribute	*bus_attrs;
	/*指向对象的指针,该对象包含设备属性和用于导出此属性sysfs文件系统的方法*/
	struct device_attribute	*dev_attrs;
	/*指向对象的指针,该对象包含设备驱动程序属性和用于导出此属性到sysfs文件
	的方法*/
	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 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 */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */

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

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};

类描述符

/*
 * device classes
 */
struct class {
	const char		*name;
	struct module		*owner;

	struct class_attribute		*class_attrs;
	struct device_attribute		*dev_attrs;
	struct kobject			*dev_kobj;

	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
	char *(*devnode)(struct device *dev, mode_t *mode);

	void (*class_release)(struct class *class);
	void (*dev_release)(struct device *dev);

	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	const struct dev_pm_ops *pm;

	struct class_private *p;
};

下面数据结构用以描述结构间关系的

/**
 * struct device_private - structure to hold the private to the driver core portions of the device structure.
 *
 * @klist_children - klist containing all children of this device
 * @knode_parent - node in sibling list
 * @knode_driver - node in driver list
 * @knode_bus - node in bus list
 * @driver_data - private pointer for driver specific info.  Will turn into a
 * list soon.
 * @device - pointer back to the struct class that this structure is
 * associated with.
 *
 * Nothing outside of the driver core should ever touch these fields.
 */
struct device_private {
	struct klist klist_children;
	struct klist_node knode_parent;
	struct klist_node knode_driver;
	struct klist_node knode_bus;
	void *driver_data;
	struct device *device;
};
struct class_private {
	struct kset class_subsys;
	struct klist class_devices;
	struct list_head class_interfaces;
	struct kset class_dirs;
	struct mutex class_mutex;
	struct class *class;
};
/**
 * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
 *
 * @subsys - the struct kset that defines this bus.  This is the main kobject
 * @drivers_kset - the list of drivers associated with this bus
 * @devices_kset - the list of devices associated with this bus
 * @klist_devices - the klist to iterate over the @devices_kset
 * @klist_drivers - the klist to iterate over the @drivers_kset
 * @bus_notifier - the bus notifier list for anything that cares about things
 * on this bus.
 * @bus - pointer back to the struct bus_type that this structure is associated
 * with.
 *
 * This structure is the one that is the actual kobject allowing struct
 * bus_type to be statically allocated safely.  Nothing outside of the driver
 * core should ever touch these fields.
 */
struct bus_type_private {
	struct kset subsys;
	struct kset *drivers_kset;
	struct kset *devices_kset;
	struct klist klist_devices;
	struct klist klist_drivers;
	struct blocking_notifier_head bus_notifier;
	unsigned int drivers_autoprobe:1;
	struct bus_type *bus;
};

struct driver_private {
	struct kobject kobj;
	struct klist klist_devices;
	struct klist_node knode_bus;
	struct module_kobject *mkobj;
	struct device_driver *driver;
};

描述属性文件的结构

/* FIXME
 * The *owner field is no longer used.
 * x86 tree has been cleaned up. The owner
 * attribute is still left for other arches.
 */
struct attribute {
	const char		*name;
	struct module		*owner;
	mode_t			mode;
};

后面有时间我会补上上面数据结构之间的关系图,便于理解。

二、原理与源码解析

解决问题我还是习惯追根溯源,我们从内核启动对设备驱动模型初始化开始看起,设备驱动中sys/文件系统的初始化工作为start_kernel()->rest_init()->

static noinline void __init_refok rest_init(void)
	__releases(kernel_lock)
{
	……
	/*创建并启动内核线程kernel_init用于初始化一些
	内核部件工作*/
	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
	……
}

内核线程kernel_init()用于驱动的初始化

kernel_init()->do_basic_setup()->driver_init()

/**
 * driver_init - initialize driver model.
 *
 * Call the driver model init functions to initialize their
 * subsystems. Called early from init/main.c.
 */
 /*在内核初始化时的线程中调用*/
void __init driver_init(void)
{
	/* These are the core pieces */
	 /*devtmpfs 的功用是在 Linux 核心 启动早期建立一个初步的 /dev,
	 令一般启动程序不用等待 udev,缩短 GNU/Linux 的开机时间。
	devtmpfs 在 2009 年初被提出,并在同年年尾进出的 Linux 2.6.32 正式收录
	*/
	devtmpfs_init();
	/*设备相关初始化*/
	devices_init();
	/*bus初始化*/
	buses_init();
	/*class初始化*/
	classes_init();
	/*firmware初始化*/
	firmware_init();
	/*虚拟化平台hypervisor初始化。虚拟化 就是通过某种方式隐藏底层物理硬件
	的过程,从而让多个操作系统可以透明地使用和共享它。这种
	架构的另一个更常见的名称是平台虚拟化。在典型的分层架构
	中,提供平台虚拟化的层称为 hypervisor (有时称为虚拟机管理程
	序 或 VMM)。来宾操作系统称为虚拟机(VM),因为对这些 VM 
	而言,硬件是专门针对它们虚拟化的。
	*/
	hypervisor_init();

	/* These are also core pieces, but must come after the
	 * core core pieces.
	 */
	platform_bus_init();
	/*初始化system_bus,即在sys/devices目录下创建system目录*/
	system_bus_init();
	/*cpu_dev初始化*/
	cpu_dev_init();
	/*在/sys/devices/system目录下创建memory目录文件
	该函数需要定义的相关宏在本机器上没有定义
	*/
	memory_dev_init();
}
/*在sys文件系统中建立几个文件夹*/
int __init devices_init(void)
{	
	/*根目录sys下创建devices文件夹*/
	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
	if (!devices_kset)
		return -ENOMEM;
	/*根目录下创建dev文件夹*/
	dev_kobj = kobject_create_and_add("dev", NULL);
	if (!dev_kobj)
		goto dev_kobj_err;
	/*在dev文件夹下创建block文件夹*/
	sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
	if (!sysfs_dev_block_kobj)
		goto block_kobj_err;
	/*在dev文件夹下创建cha
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值