Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1056357
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: LINUX

2016-04-12 15:06:11


大多数驱动程序都要实现一个probe函数,该函数在register时被调用,具体内核是如何实现的呢?下面我们以LINUX内核中Hamachi.c为例子来分析一下:


  1. static struct pci_driver hamachi_driver = {  
  2.     .name       = DRV_NAME,  
  3.     .id_table   = hamachi_pci_tbl,  
  4.     .probe      = hamachi_init_one,  
  5.     .remove     = __devexit_p(hamachi_remove_one),  
  6. };  
  7.   
  8. static int __init hamachi_init (void)  
  9. {  
  10. /* when a module, this is printed whether or not devices are found in probe */  
  11. #ifdef MODULE   
  12.     printk(version);  
  13. #endif   
  14.     return pci_register_driver(&hamachi_driver);  
  15. }  
  16.   
  17. static void __exit hamachi_exit (void)  
  18. {  
  19.     pci_unregister_driver(&hamachi_driver);  
  20. }  
  21.   
  22.   
  23. module_init(hamachi_init);  
  24. module_exit(hamachi_exit);  
[cpp] view plain copy
  1. static struct pci_driver hamachi_driver = {  
  2.     .name       = DRV_NAME,  
  3.     .id_table   = hamachi_pci_tbl,  
  4.     .probe      = hamachi_init_one,  
  5.     .remove     = __devexit_p(hamachi_remove_one),  
  6. };  
  7.   
  8. static int __init hamachi_init (void)  
  9. {  
  10. /* when a module, this is printed whether or not devices are found in probe */  
  11. #ifdef MODULE  
  12.     printk(version);  
  13. #endif  
  14.     return pci_register_driver(&hamachi_driver);  
  15. }  
  16.   
  17. static void __exit hamachi_exit (void)  
  18. {  
  19.     pci_unregister_driver(&hamachi_driver);  
  20. }  
  21.   
  22.   
  23. module_init(hamachi_init);  
  24. module_exit(hamachi_exit);  

首先,实现了一个pci_driver结构体,名为hamachi_driver,


在hamachi_init函数中,直接调用pci_register_driver,追踪该函数:


  1. /* 
  2.  * pci_register_driver must be a macro so that KBUILD_MODNAME can be expanded 
  3.  */  
  4. #define pci_register_driver(driver)     \   
  5.     __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)  
[cpp] view plain copy
  1. /* 
  2.  * pci_register_driver must be a macro so that KBUILD_MODNAME can be expanded 
  3.  */  
  4. #define pci_register_driver(driver)     \  
  5.     __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)  

发现pci_register_driver实际上是一个macro,使用宏的目的是扩展参数,实际调用的是__pci_register_driver,继续追踪:



  1. /** 
  2.  * __pci_register_driver - register a new pci driver 
  3.  * @drv: the driver structure to register 
  4.  * @owner: owner module of drv 
  5.  * @mod_name: module name string 
  6.  *  
  7.  * Adds the driver structure to the list of registered drivers. 
  8.  * Returns a negative value on error, otherwise 0.  
  9.  * If no error occurred, the driver remains registered even if  
  10.  * no device was claimed during registration. 
  11.  */  
  12. int __pci_register_driver(struct pci_driver *drv, struct module *owner,  
  13.               const char *mod_name)  
  14. {  
  15.     int error;  
  16.   
  17.     /* initialize common driver fields */  
  18.     drv->driver.name = drv->name;  
  19.     drv->driver.bus = &pci_bus_type;  
  20.     drv->driver.owner = owner;  
  21.     drv->driver.mod_name = mod_name;  
  22.   
  23.     if (drv->pm)  
  24.         drv->driver.pm = &drv->pm->base;  
  25.   
  26.     spin_lock_init(&drv->dynids.lock);  
  27.     INIT_LIST_HEAD(&drv->dynids.list);  
  28.   
  29.     /* register with core */  
  30.     error = driver_register(&drv->driver);  
  31.     if (error)  
  32.         return error;  
  33.   
  34.     error = pci_create_newid_file(drv);  
  35.     if (error)  
  36.         driver_unregister(&drv->driver);  
  37.   
  38.     return error;  
[cpp] view plain copy
  1. /** 
  2.  * __pci_register_driver - register a new pci driver 
  3.  * @drv: the driver structure to register 
  4.  * @owner: owner module of drv 
  5.  * @mod_name: module name string 
  6.  *  
  7.  * Adds the driver structure to the list of registered drivers. 
  8.  * Returns a negative value on error, otherwise 0.  
  9.  * If no error occurred, the driver remains registered even if  
  10.  * no device was claimed during registration. 
  11.  */  
  12. int __pci_register_driver(struct pci_driver *drv, struct module *owner,  
  13.               const char *mod_name)  
  14. {  
  15.     int error;  
  16.   
  17.     /* initialize common driver fields */  
  18.     drv->driver.name = drv->name;  
  19.     drv->driver.bus = &pci_bus_type;  
  20.     drv->driver.owner = owner;  
  21.     drv->driver.mod_name = mod_name;  
  22.   
  23.     if (drv->pm)  
  24.         drv->driver.pm = &drv->pm->base;  
  25.   
  26.     spin_lock_init(&drv->dynids.lock);  
  27.     INIT_LIST_HEAD(&drv->dynids.list);  
  28.   
  29.     /* register with core */  
  30.     error = driver_register(&drv->driver);  
  31.     if (error)  
  32.         return error;  
  33.   
  34.     error = pci_create_newid_file(drv);  
  35.     if (error)  
  36.         driver_unregister(&drv->driver);  
  37.   
  38.     return error;  
}


前面填充了drv->driver结构,然后调用spin_lock_init来初始化自旋锁,调用INIT_LIST_HEAD来初始化一个双向链表,核心是调用了driver_register函数,继续追踪:


  1. int driver_register(struct device_driver *drv)  
  2. {  
  3.     int ret;  
  4.     struct device_driver *other;  
  5.   
  6.     if ((drv->bus->probe && drv->probe) ||  
  7.         (drv->bus->remove && drv->remove) ||  
  8.         (drv->bus->shutdown && drv->shutdown))  
  9.         printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  10.             "bus_type methods\n", drv->name);  
  11.   
  12.     other = driver_find(drv->name, drv->bus);  
  13.     if (other) {  
  14.         put_driver(other);  
  15.         printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  16.             "aborting...\n", drv->name);  
  17.         return -EBUSY;  
  18.     }  
  19.   
  20.     ret = bus_add_driver(drv);  
  21.     if (ret)  
  22.         return ret;  
  23.     ret = driver_add_groups(drv, drv->groups);  
  24.     if (ret)  
  25.         bus_remove_driver(drv);  
  26.     return ret;  
  27. }  
[cpp] view plain copy
  1. int driver_register(struct device_driver *drv)  
  2. {  
  3.     int ret;  
  4.     struct device_driver *other;  
  5.   
  6.     if ((drv->bus->probe && drv->probe) ||  
  7.         (drv->bus->remove && drv->remove) ||  
  8.         (drv->bus->shutdown && drv->shutdown))  
  9.         printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  10.             "bus_type methods\n", drv->name);  
  11.   
  12.     other = driver_find(drv->name, drv->bus);  
  13.     if (other) {  
  14.         put_driver(other);  
  15.         printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  16.             "aborting...\n", drv->name);  
  17.         return -EBUSY;  
  18.     }  
  19.   
  20.     ret = bus_add_driver(drv);  
  21.     if (ret)  
  22.         return ret;  
  23.     ret = driver_add_groups(drv, drv->groups);  
  24.     if (ret)  
  25.         bus_remove_driver(drv);  
  26.     return ret;  
  27. }  
该函数首先做了一些检查,实际上是重点是调用了bus_add_drvier函数,进入该函数:



  1. /** 
  2.  * bus_add_driver - Add a driver to the bus. 
  3.  * @drv: driver. 
  4.  */  
  5. int bus_add_driver(struct device_driver *drv)  
  6. {  
  7.     struct bus_type *bus;  
  8.     struct driver_private *priv;  
  9.     int error = 0;  
  10.   
  11.     bus = bus_get(drv->bus);  
  12.     if (!bus)  
  13.         return -EINVAL;  
  14.   
  15.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);  
  16.   
  17.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  18.     if (!priv) {  
  19.         error = -ENOMEM;  
  20.         goto out_put_bus;  
  21.     }  
  22.     klist_init(&priv->klist_devices, NULL, NULL);  
  23.     priv->driver = drv;  
  24.     drv->p = priv;  
  25.     priv->kobj.kset = bus->p->drivers_kset;  
  26.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  27.                      "%s", drv->name);  
  28.     if (error)  
  29.         goto out_unregister;  
  30.   
  31.     if (drv->bus->p->drivers_autoprobe) {  
  32.         error = driver_attach(drv);  
  33.         if (error)  
  34.             goto out_unregister;  
  35.     }  
  36.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  37.     module_add_driver(drv->owner, drv);  
  38.   
  39.     error = driver_create_file(drv, &driver_attr_uevent);  
  40.     if (error) {  
  41.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",  
  42.             __func__, drv->name);  
  43.     }  
  44.     error = driver_add_attrs(bus, drv);  
  45.     if (error) {  
  46.         /* How the hell do we get out of this pickle? Give up */  
  47.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  
  48.             __func__, drv->name);  
  49.     }  
  50.     error = add_bind_files(drv);  
  51.     if (error) {  
  52.         /* Ditto */  
  53.         printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  
  54.             __func__, drv->name);  
  55.     }  
  56.   
  57.     kobject_uevent(&priv->kobj, KOBJ_ADD);  
  58.     return error;  
  59. out_unregister:  
  60.     kobject_put(&priv->kobj);  
  61. out_put_bus:  
  62.     bus_put(bus);  
  63.     return error;  
  64. }  
[cpp] view plain copy
  1. /** 
  2.  * bus_add_driver - Add a driver to the bus. 
  3.  * @drv: driver. 
  4.  */  
  5. int bus_add_driver(struct device_driver *drv)  
  6. {  
  7.     struct bus_type *bus;  
  8.     struct driver_private *priv;  
  9.     int error = 0;  
  10.   
  11.     bus = bus_get(drv->bus);  
  12.     if (!bus)  
  13.         return -EINVAL;  
  14.   
  15.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);  
  16.   
  17.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  18.     if (!priv) {  
  19.         error = -ENOMEM;  
  20.         goto out_put_bus;  
  21.     }  
  22.     klist_init(&priv->klist_devices, NULL, NULL);  
  23.     priv->driver = drv;  
  24.     drv->p = priv;  
  25.     priv->kobj.kset = bus->p->drivers_kset;  
  26.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  27.                      "%s", drv->name);  
  28.     if (error)  
  29.         goto out_unregister;  
  30.   
  31.     if (drv->bus->p->drivers_autoprobe) {  
  32.         error = driver_attach(drv);  
  33.         if (error)  
  34.             goto out_unregister;  
  35.     }  
  36.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  37.     module_add_driver(drv->owner, drv);  
  38.   
  39.     error = driver_create_file(drv, &driver_attr_uevent);  
  40.     if (error) {  
  41.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",  
  42.             __func__, drv->name);  
  43.     }  
  44.     error = driver_add_attrs(bus, drv);  
  45.     if (error) {  
  46.         /* How the hell do we get out of this pickle? Give up */  
  47.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  
  48.             __func__, drv->name);  
  49.     }  
  50.     error = add_bind_files(drv);  
  51.     if (error) {  
  52.         /* Ditto */  
  53.         printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  
  54.             __func__, drv->name);  
  55.     }  
  56.   
  57.     kobject_uevent(&priv->kobj, KOBJ_ADD);  
  58.     return error;  
  59. out_unregister:  
  60.     kobject_put(&priv->kobj);  
  61. out_put_bus:  
  62.     bus_put(bus);  
  63.     return error;  
  64. }  
该函数前面还是一些分配资源和初始化的工作,直到driver_attach函数,该函数的作用是遍历总线上所有的设备,将驱动与设备绑定:



  1. int driver_attach(struct device_driver *drv)  
  2. {  
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  4. }  
[cpp] view plain copy
  1. int driver_attach(struct device_driver *drv)  
  2. {  
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  4. }  



进入bus_for_each_dev函数中,



[html] view plaincopy
  1. int bus_for_each_dev(struct bus_type *bus, struct device *start,  
  2.              void *data, int (*fn)(struct device *, void *))  
  3. {  
  4.     struct klist_iter i;  
  5.     struct device *dev;  
  6.     int error = 0;  
  7.   
  8.     if (!bus)  
  9.         return -EINVAL;  
  10.   
  11.     klist_iter_init_node(&bus->p->klist_devices, &i,  
  12.                  (start ? &start->knode_bus : NULL));  
  13.     while ((dev = next_device(&i)) && !error)  
  14.         error = fn(dev, data);  
  15.     klist_iter_exit(&i);  
  16.     return error;  
  17. }  
[html] view plain copy
  1. int bus_for_each_dev(struct bus_type *bus, struct device *start,  
  2.              void *data, int (*fn)(struct device *, void *))  
  3. {  
  4.     struct klist_iter i;  
  5.     struct device *dev;  
  6.     int error = 0;  
  7.   
  8.     if (!bus)  
  9.         return -EINVAL;  
  10.   
  11.     klist_iter_init_node(&bus->p->klist_devices, &i,  
  12.                  (start ? &start->knode_bus : NULL));  
  13.     while ((dev = next_device(&i)) && !error)  
  14.         error = fn(dev, data);  
  15.     klist_iter_exit(&i);  
  16.     return error;  
  17. }  
该函数的重点是调用了fn这个函数指针实现回调,回调函数为__driver_attach,进入该函数:



  1. static int __driver_attach(struct device *dev, void *data)  
  2. {  
  3.     struct device_driver *drv = data;  
  4.   
  5.     /* 
  6.      * Lock device and try to bind to it. We drop the error 
  7.      * here and always return 0, because we need to keep trying 
  8.      * to bind to devices and some drivers will return an error 
  9.      * simply if it didn't support the device. 
  10.      * 
  11.      * driver_probe_device() will spit a warning if there 
  12.      * is an error. 
  13.      */  
  14.   
  15.     if (dev->parent) /* Needed for USB */  
  16.         down(&dev->parent->sem);  
  17.     down(&dev->sem);  
  18.     if (!dev->driver)  
  19.         driver_probe_device(drv, dev);  
  20.     up(&dev->sem);  
  21.     if (dev->parent)  
  22.         up(&dev->parent->sem);  
  23.   
  24.     return 0;  
  25. }  
[cpp] view plain copy
  1. static int __driver_attach(struct device *dev, void *data)  
  2. {  
  3.     struct device_driver *drv = data;  
  4.   
  5.     /* 
  6.      * Lock device and try to bind to it. We drop the error 
  7.      * here and always return 0, because we need to keep trying 
  8.      * to bind to devices and some drivers will return an error 
  9.      * simply if it didn't support the device. 
  10.      * 
  11.      * driver_probe_device() will spit a warning if there 
  12.      * is an error. 
  13.      */  
  14.   
  15.     if (dev->parent) /* Needed for USB */  
  16.         down(&dev->parent->sem);  
  17.     down(&dev->sem);  
  18.     if (!dev->driver)  
  19.         driver_probe_device(drv, dev);  
  20.     up(&dev->sem);  
  21.     if (dev->parent)  
  22.         up(&dev->parent->sem);  
  23.   
  24.     return 0;  
  25. }  

重点进入driver_probe_device函数,



  1. /** 
  2.  * driver_probe_device - attempt to bind device & driver together 
  3.  * @drv: driver to bind a device to 
  4.  * @dev: device to try to bind to the driver 
  5.  * 
  6.  * First, we call the bus's match function, if one present, which should 
  7.  * compare the device IDs the driver supports with the device IDs of the 
  8.  * device. Note we don't do this ourselves because we don't know the 
  9.  * format of the ID structures, nor what is to be considered a match and 
  10.  * what is not. 
  11.  * 
  12.  * This function returns 1 if a match is found, -ENODEV if the device is 
  13.  * not registered, and 0 otherwise. 
  14.  * 
  15.  * This function must be called with @dev->sem held.  When called for a 
  16.  * USB interface, @dev->parent->sem must be held as well. 
  17.  */  
  18. int driver_probe_device(struct device_driver *drv, struct device *dev)  
  19. {  
  20.     int ret = 0;  
  21.   
  22.     if (!device_is_registered(dev))  
  23.         return -ENODEV;  
  24.     if (drv->bus->match && !drv->bus->match(dev, drv))  
  25.         goto done;  
  26.   
  27.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",  
  28.          drv->bus->name, __func__, dev->bus_id, drv->name);  
  29.   
  30.     ret = really_probe(dev, drv);  
  31.   
  32. done:  
  33.     return ret;  
  34. }  
[cpp] view plain copy
  1. /** 
  2.  * driver_probe_device - attempt to bind device & driver together 
  3.  * @drv: driver to bind a device to 
  4.  * @dev: device to try to bind to the driver 
  5.  * 
  6.  * First, we call the bus's match function, if one present, which should 
  7.  * compare the device IDs the driver supports with the device IDs of the 
  8.  * device. Note we don't do this ourselves because we don't know the 
  9.  * format of the ID structures, nor what is to be considered a match and 
  10.  * what is not. 
  11.  * 
  12.  * This function returns 1 if a match is found, -ENODEV if the device is 
  13.  * not registered, and 0 otherwise. 
  14.  * 
  15.  * This function must be called with @dev->sem held.  When called for a 
  16.  * USB interface, @dev->parent->sem must be held as well. 
  17.  */  
  18. int driver_probe_device(struct device_driver *drv, struct device *dev)  
  19. {  
  20.     int ret = 0;  
  21.   
  22.     if (!device_is_registered(dev))  
  23.         return -ENODEV;  
  24.     if (drv->bus->match && !drv->bus->match(dev, drv))  
  25.         goto done;  
  26.   
  27.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",  
  28.          drv->bus->name, __func__, dev->bus_id, drv->name);  
  29.   
  30.     ret = really_probe(dev, drv);  
  31.   
  32. done:  
  33.     return ret;  
  34. }  

该函数的作用是将设备和驱动程序绑定,首先调用match函数指针,检查设备和驱动是否匹配,然后调用了really_probe,真正的probe:



  1. static int really_probe(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     atomic_inc(&probe_count);  
  6.     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",  
  7.          drv->bus->name, __func__, drv->name, dev->bus_id);  
  8.     WARN_ON(!list_empty(&dev->devres_head));  
  9.   
  10.     dev->driver = drv;  
  11.     if (driver_sysfs_add(dev)) {  
  12.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",  
  13.             __func__, dev->bus_id);  
  14.         goto probe_failed;  
  15.     }  
  16.   
  17.     if (dev->bus->probe) {  
  18.         ret = dev->bus->probe(dev);  
  19.         if (ret)  
  20.             goto probe_failed;  
  21.     } else if (drv->probe) {  
  22.         ret = drv->probe(dev);  
  23.         if (ret)  
  24.             goto probe_failed;  
  25.     }  
  26.   
  27.     driver_bound(dev);  
  28.     ret = 1;  
  29.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",  
  30.          drv->bus->name, __func__, dev->bus_id, drv->name);  
  31.     goto done;  
  32.   
  33. probe_failed:  
  34.     devres_release_all(dev);  
  35.     driver_sysfs_remove(dev);  
  36.     dev->driver = NULL;  
  37.   
  38.     if (ret != -ENODEV && ret != -ENXIO) {  
  39.         /* driver matched but the probe failed */  
  40.         printk(KERN_WARNING  
  41.                "%s: probe of %s failed with error %d\n",  
  42.                drv->name, dev->bus_id, ret);  
  43.     }  
  44.     /* 
  45.      * Ignore errors returned by ->probe so that the next driver can try 
  46.      * its luck. 
  47.      */  
  48.     ret = 0;  
  49. done:  
  50.     atomic_dec(&probe_count);  
  51.     wake_up(&probe_waitqueue);  
  52.     return ret;  
  53. }  
[cpp] view plain copy
  1. static int really_probe(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     atomic_inc(&probe_count);  
  6.     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",  
  7.          drv->bus->name, __func__, drv->name, dev->bus_id);  
  8.     WARN_ON(!list_empty(&dev->devres_head));  
  9.   
  10.     dev->driver = drv;  
  11.     if (driver_sysfs_add(dev)) {  
  12.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",  
  13.             __func__, dev->bus_id);  
  14.         goto probe_failed;  
  15.     }  
  16.   
  17.     if (dev->bus->probe) {  
  18.         ret = dev->bus->probe(dev);  
  19.         if (ret)  
  20.             goto probe_failed;  
  21.     } else if (drv->probe) {  
  22.         ret = drv->probe(dev);  
  23.         if (ret)  
  24.             goto probe_failed;  
  25.     }  
  26.   
  27.     driver_bound(dev);  
  28.     ret = 1;  
  29.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",  
  30.          drv->bus->name, __func__, dev->bus_id, drv->name);  
  31.     goto done;  
  32.   
  33. probe_failed:  
  34.     devres_release_all(dev);  
  35.     driver_sysfs_remove(dev);  
  36.     dev->driver = NULL;  
  37.   
  38.     if (ret != -ENODEV && ret != -ENXIO) {  
  39.         /* driver matched but the probe failed */  
  40.         printk(KERN_WARNING  
  41.                "%s: probe of %s failed with error %d\n",  
  42.                drv->name, dev->bus_id, ret);  
  43.     }  
  44.     /* 
  45.      * Ignore errors returned by ->probe so that the next driver can try 
  46.      * its luck. 
  47.      */  
  48.     ret = 0;  
  49. done:  
  50.     atomic_dec(&probe_count);  
  51.     wake_up(&probe_waitqueue);  
  52.     return ret;  
  53. }  

直到这里才利用drv->probe指针,该指针指向的是:



  1. struct device_driver {  
  2.     const char        *name;  
  3.     struct bus_type        *bus;  
  4.   
  5.     struct module        *owner;  
  6.     const char         *mod_name;    /* used for built-in modules */  
  7.   
  8.     int (*probe) (struct device *dev);  
  9.     int (*remove) (struct device *dev);  
  10.     void (*shutdown) (struct device *dev);  
  11.     int (*suspend) (struct device *dev, pm_message_t state);  
  12.     int (*resume) (struct device *dev);  
  13.     struct attribute_group **groups;  
  14.   
  15.     struct pm_ops *pm;  
  16.   
  17.     struct driver_private *p;  
  18. };  
[cpp] view plain copy
  1. struct device_driver {  
  2.     const char        *name;  
  3.     struct bus_type        *bus;  
  4.   
  5.     struct module        *owner;  
  6.     const char         *mod_name;    /* used for built-in modules */  
  7.   
  8.     int (*probe) (struct device *dev);  
  9.     int (*remove) (struct device *dev);  
  10.     void (*shutdown) (struct device *dev);  
  11.     int (*suspend) (struct device *dev, pm_message_t state);  
  12.     int (*resume) (struct device *dev);  
  13.     struct attribute_group **groups;  
  14.   
  15.     struct pm_ops *pm;  
  16.   
  17.     struct driver_private *p;  
  18. };  
中的probe函数指针,该结构体是需要你在register之前实现的,直到此时才
真正的调用了hamachi.c中你实现的probe函数。
阅读(1509) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~