device结构体定义,在kernel-4.7/include/linux/device.h中:
/**
* struct device - The basic device structure
* @driver_data: Private pointer for driver specific info.
* @power: For device power management.
* See Documentation/power/devices.txt for details.
* @pm_domain: Provide callbacks that are executed during system suspend,
* hibernation, system resume and during runtime PM transitions
* along with subsystem-level and driver-level callbacks.
* @pins: For device pin management.
* See Documentation/pinctrl.txt for details.
* @msi_list: Hosts MSI descriptors
* @msi_domain: The generic MSI domain this device is using.
* @numa_node: NUMA node this device is close to.
* @dma_mask: Dma mask (if dma'ble device).
* @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
* hardware supports 64-bit addresses for consistent allocations
* such descriptors.
* @dma_pfn_offset: offset of DMA memory range relatively of RAM
* @dma_parms: A low level driver may set these to teach IOMMU code about
* segment limitations.
* @dma_pools: Dma pools (if dma'ble device).
* @dma_mem: Internal for coherent mem override.
* @cma_area: Contiguous memory area for dma allocations
* @archdata: For arch-specific additions.
* @of_node: Associated device tree node.
* @fwnode: Associated device node supplied by platform firmware.
* @devt: For creating the sysfs "dev".
* @id: device instance
* @devres_lock: Spinlock to protect the resource of the device.
* @devres_head: The resources list of the device.
* @knode_class: The node used to add the device to the class list.
* @class: The class of the device.
* @groups: Optional attribute groups.
* @release: Callback to free the device after all references have
* gone away. This should be set by the allocator of the
* device (i.e. the bus driver that discovered the device).
* @iommu_group: IOMMU group the device belongs to.
*
* @offline_disabled: If set, the device is permanently online.
* @offline: Set after successful invocation of bus type's .offline().
*
* At the lowest level, every device in a Linux system is represented by an
* instance of struct device. The device structure contains the information
* that the device model core needs to model the system. Most subsystems,
* however, track additional information about the devices they host. As a
* result, it is rare for devices to be represented by bare device structures;
* instead, that structure, like kobject structures, is usually embedded within
* a higher-level representation of the device.
*/
struct device {
struct device *parent; //指向其父设备。
struct device_private *p; // 设备驱动部分的核心私有数据
struct kobject kobj; // kobject类, 用于联系到sysfs中
const char *init_name; /* initial name of the device */
const struct device_type *type; //表示设备的类型
struct mutex mutex; /* mutex 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 */
void *driver_data; /* Driver data, set and get with
dev_set/get_drvdata */
struct dev_pm_info power;
struct dev_pm_domain *pm_domain;
#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
struct irq_domain *msi_domain;
#endif
#ifdef CONFIG_PINCTRL
struct dev_pin_info *pins;
#endif
#ifdef CONFIG_GENERIC_MSI_IRQ
struct list_head msi_list;
#endif
#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. */
unsigned long dma_pfn_offset;
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 */
#ifdef CONFIG_DMA_CMA
struct cma *cma_area; /* contiguous memory area for dma
allocations */
#endif
/* arch specific additions */
struct dev_archdata archdata;
struct device_node *of_node; /* associated device tree node */
struct fwnode_handle *fwnode; /* firmware device node */
dev_t devt; /* dev_t, creates the sysfs "dev" */
u32 id; /* device instance */
spinlock_t devres_lock;
struct list_head devres_head;
struct klist_node knode_class; //连入class链表时所用的klist节点
struct class *class; //指向类的指针
const struct attribute_group **groups; /* optional groups 设备的属性集合*/
void (*release)(struct device *dev); //设备释放时调用的函数
struct iommu_group *iommu_group;
bool offline_disabled:1;
bool offline:1;
};
device结构体用于描述设备相关的信息设备之间的层次关系,以及设备与总线、驱动的关系。
/**
* 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
* @deferred_probe - entry in deferred_probe_list which is used to retry the
* binding of drivers which were unable to get all the resources needed by
* the device; typically because it depends on another driver getting
* probed first.
* @device - pointer back to the struct device 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; //连入父设备的klist_children时所用的节点
struct klist_node knode_driver; //连入驱动的设备链表所用的节点
struct klist_node knode_bus; //连入总线的设备链表时所用的节点
struct list_head deferred_probe;
struct device *device;
};
//从父设备的klist_children上节点,获得相应的device_private
#define to_device_private_parent(obj) \
container_of(obj, struct device_private, knode_parent)
//从驱动的设备链表上节点,获得对应的device_private
#define to_device_private_driver(obj) \
container_of(obj, struct device_private, knode_driver)
从总线的设备链表上节点,获得对应的device_private
#define to_device_private_bus(obj) \
container_of(obj, struct device_private, knode_bus)
struct device
中有一部分不愿意让外界看到,所以做出struct device_private
结构,包括了设备驱动模型内部的链接。这个结构体定义在drivers/base/base.h文件中。
Linux设备模型中,device相关的sysfs结构的初始化是由devices_init
函数完成的,该函数定义在drivers/base/core.c文件中,其内容如下:
int __init devices_init(void)
{
//创建devices_kset,它是所有device的集合,它的名字是“devices”,对应/sys/devices目录
devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
if (!devices_kset)
return -ENOMEM;
//创建dev_kobj,它的名字是“dev”,对应/sys/dev目录
dev_kobj = kobject_create_and_add("dev", NULL);
if (!dev_kobj)
goto dev_kobj_err;
//创建sysfs_dev_block_kobj,它的名字是“block”,对应/sys/dev/block目录
sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
if (!sysfs_dev_block_kobj)
goto block_kobj_err;
创建sysfs_dev_char_kobj,它的名字是“char”,对应/sys/dev/char目录
sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
if (!sysfs_dev_char_kobj)
goto char_kobj_err;
return 0;
char_kobj_err:
kobject_put(sysfs_dev_block_kobj);
block_kobj_err:
kobject_put(dev_kobj);
dev_kobj_err:
kset_unregister(devices_kset);
return -ENOMEM;
}
注册一个device是通过调用device_register
函数完成的,该函数定义在drivers/base/core.c文件中,其内容如下:
/**
* device_regi