本文主要是介绍《Linux内核编程》第十五章:Linux设备模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本文基于mstar801平台Linux2.6.35.11。
一、底层数据结构kset及kobject
kernel2.6.35.11/include/linux/kobject.h
struct kobject {const char *name; struct list_head entry;struct kobject *parent;struct kset *kset;struct kobj_type *ktype;struct sysfs_dirent *sd;struct kref kref;unsigned int state_initialized:1;unsigned int state_in_sysfs:1;unsigned int state_add_uevent_sent:1;unsigned int state_remove_uevent_sent:1;unsigned int uevent_suppress:1;
};
struct kset {struct list_head list;spinlock_t list_lock;struct kobject kobj;const struct kset_uevent_ops *uevent_ops;
};
kernel2.6.35.11/lib/kobject.c
EXPORT_SYMBOL_GPL(kobject_get_path);
EXPORT_SYMBOL_GPL(kobject_init_and_add);
EXPORT_SYMBOL_GPL(kobject_rename);
EXPORT_SYMBOL_GPL(kobject_create_and_add);
EXPORT_SYMBOL_GPL(kset_create_and_add);
kobject:
kobject是Linux2.6引入的新的设备管理机制,通过这个数据结构使所有设备在底层都具有统一接口。
总线、设备和驱动就是通过kobject连接起来的;一般用于设备和驱动模型。
结合面向对象的思想,任何一个设备模型:总线、设备和驱动都属于一个kobject,这种派生关系就是在结构体中包含一个kobject的变量。
该结构体提供了所有模型需要的最基本的功能:引用计数,sysfs表示,热插拔事件处理。
内核用kobject结构将各个对象组成一个分层的结构体系,与模块化的子系统相匹配;有两个独立的机制用于连接:parent指针和kset域。
kset:
kset是管理kobject的集合;一般用于总线模型。
kobject通常通过kset组成成层次化的结构,kset是具有相同类型的kobject的集合;kset数据结构内嵌了一个kobject对象,所有属于kset的kobject对象的parent域都指向这个内嵌的对象。
二、基于底层数据结构kobject的设备模型:总线,设备,驱动
1.总线——bus_type:
kernel2.6.35.11/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);const struct dev_pm_ops *pm;struct subsys_private *p; //总线类型私有数据
};
kernel2.6.35.11/drivers/base/base.h
struct subsys_private {struct kset subsys; //与该总线相关的子系统struct kset *devices_kset; //挂载在总线上的设备ksetstruct kset *drivers_kset; //总线驱动程序的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 list_head class_interfaces;struct kset glue_dirs;struct mutex class_mutex;struct class *class;
};
说明:从上边结构体可以看出:一条总线拥有两条链表;一条是设备链表、一条是驱动链表。有了总线对应的数据结构,就可以获得总线关联了多少设备、以及有哪些驱动来支持这类设备。
后来注册的设备\驱动就是添加到kset中的。
kernel2.6.35.11/drivers/base/bus.c
EXPORT_SYMBOL_GPL(bus_register);
EXPORT_SYMBOL_GPL(bus_unregister);
EXPORT_SYMBOL_GPL(bus_register_notifier);
EXPORT_SYMBOL_GPL(bus_unregister_notifier);
EXPORT_SYMBOL_GPL(bus_get_kset);
EXPORT_SYMBOL_GPL(bus_get_device_klist);
EXPORT_SYMBOL_GPL(bus_create_file);
EXPORT_SYMBOL_GPL(bus_remove_file);
EXPORT_SYMBOL_GPL(bus_for_each_dev);
EXPORT_SYMBOL_GPL(bus_find_device);
EXPORT_SYMBOL_GPL(bus_find_device_by_name);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
EXPORT_SYMBOL_GPL(bus_rescan_devices);
EXPORT_SYMBOL_GPL(device_reprobe);
EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
2.设备——device:
kernel2.6.35.11/include/linux/device.h
struct device {struct device *parent; //父设备struct device_private *p; //设备结构的私有数据struct kobject kobj; //kobject对象const char *init_name; //设备初始化名字const struct device_type *type; //设备方法struct mutex mutex; //信号量struct bus_type *bus; //设备所在总线struct device_driver *driver; //该设备的驱动void *platform_data; //平台总线私有数据struct dev_pm_info power;struct dev_power_domain *pwr_domain;
#ifdef CONFIG_NUMAint numa_node; /* NUMA node this device is close to */
#endifu64 *dma_mask; /* dma mask (if dma'able device) */u64 coherent_dma_mask;/* Like dma_mask, but foralloc_coherent mappings asnot all hardware supports64 bit addresses for consistentallocations 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 memoverride *//* arch specific additions */struct dev_archdata archdata;struct device_node *of_node; /* associated device tree node */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);
};
kernel2.6.35.11/drivers/base/base.h
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;
};
说明:利用结构中的kobject跟kset进行关联;在进行设备注册时,将设备添加到总线中去。
kernel2.6.35.11/drivers/base/core.c
EXPORT_SYMBOL_GPL(device_add);
EXPORT_SYMBOL_GPL(device_del);
EXPORT_SYMBOL_GPL(device_register);
EXPORT_SYMBOL_GPL(device_unregister);
EXPORT_SYMBOL_GPL(device_for_each_child);
EXPORT_SYMBOL_GPL(device_find_child);
EXPORT_SYMBOL_GPL(device_initialize);
EXPORT_SYMBOL_GPL(get_device);
EXPORT_SYMBOL_GPL(put_device);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
EXPORT_SYMBOL_GPL(__root_device_register);
EXPORT_SYMBOL_GPL(root_device_unregister);
EXPORT_SYMBOL_GPL(device_create_vargs);
EXPORT_SYMBOL_GPL(device_create);
EXPORT_SYMBOL_GPL(device_destroy);
EXPORT_SYMBOL_GPL(device_rename);
EXPORT_SYMBOL_GPL(device_move);
EXPORT_SYMBOL_GPL(device_create_bin_file);
EXPORT_SYMBOL_GPL(device_remove_bin_file);
EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
EXPORT_SYMBOL_GPL(dev_set_name);
3.驱动device_driver:
kernel2.6.35.11/include/linux/device.h
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 */const struct of_device_id *of_match_table;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;
};
kernel2.6.35.11/drivers/base/base.h
struct driver_private {struct kobject kobj;struct klist klist_devices;struct klist_node knode_bus;struct module_kobject *mkobj;struct device_driver *driver;
};
kernel2.6.35.11/drivers/base/driver.c
EXPORT_SYMBOL_GPL(driver_register);
EXPORT_SYMBOL_GPL(driver_unregister);
EXPORT_SYMBOL_GPL(driver_for_each_device);
EXPORT_SYMBOL_GPL(driver_find_device);
EXPORT_SYMBOL_GPL(driver_create_file);
EXPORT_SYMBOL_GPL(driver_remove_file);
EXPORT_SYMBOL_GPL(driver_add_kobj);
EXPORT_SYMBOL_GPL(get_driver);
EXPORT_SYMBOL_GPL(put_driver);
三、USB输入设备的总线、设备与驱动
1.USB总线,包含bus_type、间接包含kset
kernel2.6.35.11/include/linux/usb.h
extern struct bus_type usb_bus_type;
kernel2.6.35.11/drivers/usb/core/driver.c
struct bus_type usb_bus_type = {.name = "usb",.match = usb_device_match,.uevent = usb_uevent,
};
2.设备,包含device、间接包含kobject
kernel2.6.35.11/include/linux/input.h
struct input_dev{......struct device dev;......
}
3.驱动,包含device_driver、间接包含kobject
kernel2.6.35.11/include/linux/usb.h
struct usb_driver {......struct usbdrv_wrap drvwrap;......
}
struct usbdrv_wrap {struct device_driver driver;int for_devices;
};
这篇关于《Linux内核编程》第十五章:Linux设备模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!