设备模型之驱动

驱动管理一定的设备,其中的关系主要是内核的内部机制实现的,但是实现的具体逻辑需要在bus_type中的match函数中具体设计。通常是一定的设备名和驱动名匹配,当然也可以有其他的逻辑,具体的只需要设计好bus_type中的match函数。


驱动是由驱动结构体实现的。具体如下所示:

  1. /*驱动结构体*/

  2. struct device_driver {

  3.     /*驱动名,通常用来匹配设备*/

  4.     const char        *name;

  5.     /*关联的总线类型,总线、设备、驱动关联的总线类型*/

  6.     struct bus_type        *bus;

  7.     struct module        *owner;

  8.     const char         *mod_name;    /* used for built-in modules */

  9.     /*驱动中最应该实现的操作函数主要包括proberemove函数*/

  10.     /*当匹配完成以后的,入口函数*/

  11.     int (*probe) (struct device *dev);

  12.     /*驱动卸载时操作的相关函数,退出函数*/

  13.     int (*remove) (struct device *dev);

  14.     void (*shutdown) (struct device *dev);

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

  16.     int (*resume) (struct device *dev);

  17.     struct attribute_group **groups;

  18.     struct dev_pm_ops *pm;

  19.     struct driver_private *p;

  20. };

  21. /*驱动注册函数,返回值必须检测*/

  22. int __must_check driver_register(struct device_driver *drv);

  23. /*驱动释放函数*/

  24. void driver_unregister(struct device_driver *drv);

  25. /*驱动属性结构体*/

  26. struct driver_attribute {

  27.     /*属性值*/

  28.     struct attribute attr;

  29.     /*属性读操作函数*/

  30.     ssize_t (*show)(struct device_driver *driver, char *buf);

  31.     /*属性写操作函数*/

  32.     ssize_t (*store)(struct device_driver *driver, const char *buf,

  33.              size_t count);

  34. };

  35. /*驱动属性定义宏命令*/

  36. #define DRIVER_ATTR(_name, _mode, _show, _store)    

  37. struct driver_attribute driver_attr_##_name =        

  38.     __ATTR(_name, _mode, _show, _store)

 /*驱动属性文件创建函数,返回值必须检测*/ 

  1. int __must_check driver_create_file(struct device_driver *driver,struct driver_attribute *attr);

  2. /*驱动属性文件移除函数*/

  3. void driver_remove_file(struct device_driver *driver,struct driver_attribute *attr);

驱动结构体的定义不需要完成所有元素的赋值,只需要完成主要的几个变量的赋值即可,其中主要的元素包含name,bus,以及proberemove函数的实现。

其中的probe函数是当总线中的match完成匹配操作以后,进入驱动的入口函数,因此必须实现。remove我认为就是对应的退出函数,因此也有必要实现。

驱动的注册,释放也有相关的函数来操作,主要是driver_register()driver_unregister()


总结:

1、在总线驱动模型中我认为最主要的是搞清楚三个不同的结构体,分别是总线、驱动、设备。了解三个元素对应的属性结构体以及相应的属性操作函数的差异性。

2、不同驱动设计的关键主要是完成不同结构体的填充过程,但是并不需要对结构体中所有的对象进行赋值,只需要完成重要的几个元素的值。

3、总线是一种类型,同时也是一种设备,在总线的相关处理中需要首先添加总线类型,然后添加总线设备,这是需要注意的。由于总线类型关联驱动和设备,因此需要导出总线类型变量。由于总线设备是设备的父设备,因此也需要将总线设备变量导出。同样在驱动和设备中也要导出相关的结构体变量,便于总线中的match函数实现驱动和设备的匹配操作。

4XXX_attr结构体基本相同,都是一个属性结构体和函数show()stroe()。但是不同的XXX可能会导致showstroe函数的参数发生变化。这需要对照源码。

5struct device中的init_name是一个特殊的量,不能直接读写操作,只能采用函数device_name()set_device_name来设置设备名。

6xxx_register()之类的函数,需要对返回值进行检查。因为很有可能不成功。

例子

接总线与设备的代码

driver.c


#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>


MODULE_AUTHOR("David Xie");
MODULE_LICENSE("Dual BSD/GPL");


extern struct bus_type my_bus_type;


static int my_probe(struct device *dev)
{
    printk("Driver found device which my driver can handle!\n");
    return 0;
}


static int my_remove(struct device *dev)
{
    printk("Driver found device unpluged!\n");
    return 0;
}


struct device_driver my_driver = {
.name = "my_dev",
.bus = &my_bus_type,
.probe = my_probe,/*匹配完成以后的入口函数*/
        .remove = my_remove,/*驱动卸载时操作的相关函数,退出函数*/
};


/*
 * Export a simple attribute.
 */
static ssize_t mydriver_show(struct device_driver *driver, char *buf)
{
return sprintf(buf, "%s\n", "This is my driver!");
}


static DRIVER_ATTR(drv, S_IRUGO, mydriver_show, NULL);


static int __init my_driver_init(void)
{
int ret = 0;
        
        /*注册驱动*/
driver_register(&my_driver);

/*创建属性文件*/
driver_create_file(&my_driver, &driver_attr_drv);

return ret;


}


static void my_driver_exit(void)
{
driver_unregister(&my_driver);
}


module_init(my_driver_init);
module_exit(my_driver_exit);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值