linux驱动学习笔记(三) -- bus,device,device_driver之间的关系

linux驱动模型 -- bus,device,device_driver之间的关系

说明:内核2.6.28与参考有一定的不同做相应的修改,并添加一些结构体代码
参考文章: 《Linux设备驱动开发详情》第五章
http://blog.csdn.net/yinkaizhong/article/details/3896383
device:
device的结构体用于描述设备相关的设备之间的层次关系,以及设备与总线、驱动的关系。
设备就是连接在总线上的物理实体。设备是有功能之分的。具有相同功能的设备被归到一个类(CLASS中)。如音频设备(和声音相关的都算),输入设备(鼠标,键盘,游戏杆等)。。。。
从宏观考虑,任何设备必须要连接到主机才能发挥其作用。一个鼠标离开了电脑主机就不再是鼠标了。提到了连接就必然出现总线BUS。任何设备要正常运行必须有软件支持,所有的设备必须有DRIVER。设备的目的就是完成功能,根据功能的分类,该设备必然属于某个CLASS。
device结构体如下:
367struct device {
368 struct klist klist_children;/*设备列表中的孩子列表*/
369 struct klist_node knode_parent; /* node in sibling list */
370 struct klist_node knode_driver;/*驱动结点*/
371 struct klist_node knode_bus;/*总线结点*/
372 struct device *parent;/*指向父设备*/
373
374 struct kobject kobj;/*内嵌一个kobject对象*/
375 char bus_id[BUS_ID_SIZE]; /* position on parent bus */
376 const char *init_name; /* initial name of the device */
377 struct device_type *type;
378 unsigned uevent_suppress:1;
379
380 struct semaphore sem; /* semaphore to synchronize calls to
381 * its driver.
382 */
383
384 struct bus_type *bus; /* type of bus device is on */
385 struct device_driver *driver; /* which driver has allocated this
386 device */
387 void *driver_data; /* data private to the driver */
388 void *platform_data; /* Platform specific data, device
389 core doesn't touch it */
390 struct dev_pm_info power;
391
392#ifdef CONFIG_NUMA
393 int numa_node; /* NUMA node this device is close to */
394#endif
395 u64 *dma_mask; /* dma mask (if dma'able device) */
396 u64 coherent_dma_mask;/* Like dma_mask, but for
397 alloc_coherent mappings as
398 not all hardware supports
399 64 bit addresses for consistent
400 allocations such descriptors. */
401
402 struct device_dma_parameters *dma_parms;
403
404 struct list_head dma_pools; /* dma pools (if dma'ble) */
405
406 struct dma_coherent_mem *dma_mem; /* internal for coherent mem override */ 
/*...omiting some codes....*/ void (*release)(struct device *dev);};

内核提供了相应的函数用于操作device对象。(http://lxr.linux.no/linux+v2.6.28/drivers/base/core.c)
982int device_register(struct device *dev)/*将一个新的device对象插入设备模块,并自动在/sys/devices下创建一个对应的目录。*/
1087void device_unregister(struct device *dev)/*与register完成相反的操作*/
996struct device *get_device(struct device *dev)/*用于增加设备对象的引用计数*/
1005void put_device(struct device *dev)/*用于减少设备对象的引用计数*/

通常device结构体不单独使用,而是包含在更大的结构体中,比如描述PCI设备的struct pci_dev,其中的dev域就是一个device对象。
driver:
驱动程序是在CPU运行时,提供操作的软件接口。所有的设备必须有与之配套驱动程序才能正常工作。一个驱动程序可以驱动多个类似或者完全不同的设备。系统中的每个驱动程序由一个device_driver对象描述,对应的数据结构定义如下:
122struct device_driver {
123 const char *name;/*设备驱动程序的名称*/
124 struct bus_type *bus;/*总线*/
125
126 struct module *owner;
127 const char *mod_name; /* used for built-in modules */
128
129 int (*probe) (struct device *dev);/*ponit to device probe fuction*/
130 int (*remove) (struct device *dev);/*point to device remove function*/
131 void (*shutdown) (struct device *dev);
132 int (*suspend) (struct device *dev, pm_message_t state);
133 int (*resume) (struct device *dev);
134 struct attribute_group **groups;
135
136 struct pm_ops *pm;
137
138 struct driver_private *p;
139};
device_driver对象依靠内嵌的kobject对象实现引用计数管理和层次结构组织。
214int driver_register(struct device_driver *drv)/*用于向设备模型插入新的driver对象,同时sysfs文件系统中创建对应的目录。*/
bus:
总线作为主机和外设的连接通道,有些总线是比较规范的,形成了很多协议。如PCI,USB,1394,IIC等。任何设备都可以选择合适的总线连接到主机。当然主机也可能就是CPU本身。内存也是通过BUS连接到主机的,可内存使用的总线不是外设总线,因此和内存使用相同类型的总线的设备,谈及BUS比较含糊。
一块网卡在嵌入式开发中,直接通过内存总线接入到CPU。我们在写网卡驱动时,要给该BUS定义就麻烦了。
系统总线由struct bus_type描述,结构体原型如下:(http://lxr.linux.no/linux+v2.6.28/include/linux/device.h)
51struct bus_type {
52 const char *name;
53 struct bus_attribute *bus_attrs;
54 struct device_attribute *dev_attrs;
55 struct driver_attribute *drv_attrs;
56
57 int (*match)(struct device *dev, struct device_driver *drv);/*用于将device和driver相匹配后调用device_driver中的probe函数进行相应操作*/
58 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
59 int (*probe)(struct device *dev);
60 int (*remove)(struct device *dev);
61 void (*shutdown)(struct device *dev);
62
63 int (*suspend)(struct device *dev, pm_message_t state);
64 int (*suspend_late)(struct device *dev, pm_message_t state);
65 int (*resume_early)(struct device *dev);
66 int (*resume)(struct device *dev);
67
68 struct pm_ext_ops *pm;
69
70 struct bus_type_private *p;
71};

每个bus_type对应/sys/bus目录下的子目录。

/*其中'##'用于在宏中连接前后字符串*/
用于创建和初始化bus_attribte、device_attribute、driver_attribute的宏:(http://lxr.linux.no/linux+v2.6.28/include/linux/device.h)
#define BUS_ATTR(_name, _mode, _show, _store) \
struct bus_attribute bus_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
#define DRIVER_ATTR(_name, _mode, _show, _store) \
struct driver_attribute driver_attr_##_name = \
__ATTR(_name, _mode, _show, _store)

下面函数用于添加和删除bus、device、driver属性:
47extern int __must_check bus_create_file(struct bus_type *,
48 struct bus_attribute *);
49extern void bus_remove_file(struct bus_type *, struct bus_attribute *);

extern int __must_check device_create_file(struct device *device,
310 struct device_attribute *entry);
311extern void device_remove_file(struct device *dev,
312 struct device_attribute *attr);
164extern int __must_check driver_create_file(struct device_driver *driver,
165 struct driver_attribute *attr);
166extern void driver_remove_file(struct device_driver *driver,
167 struct driver_attribute *attr);

xxx_create_file()函数中会调用sysfs_create_file(),而xxx_remove_file()函数中会调用sysfs_remove_file()函数,xxx_create_file()会创建对应的sysfs文件节点,而xxx_remove_file()会删除对应的xxx文件节点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值