《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;  //挂载在总线上的设备kset
  struct 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_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;
  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;
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值