以linux-3.2內核代碼為例,結構體里面的函數的用法:
例,在某驅動文件中,定義了一個平台設備驅動:
static struct platform_driver s3c24xx_led_driver = {
.probe = s3c24xx_led_probe, .remove = s3c24xx_led_remove, .driver = { .name = "s3c24xx_led", .owner = THIS_MODULE, }, };
對struct platform_driver而言,probe平台設備注冊時需要的函數,remove是平台設備移除時時需要的函數。
對於不同的硬件,其注冊和移除的時候,有各自不同的部分操作,比如硬件上拉下拉、特殊寄存器cfg配置等。
這些不同的操作就體現在例子中的s3c24xx_led_probe, s3c24xx_led_remove中。
static int s3c24xx_led_remove(struct platform_device *dev) { struct s3c24xx_gpio_led *led = pdev_to_gpio(dev); led_classdev_unregister(&led->cdev); kfree(led); return 0; } static int s3c24xx_led_probe(struct platform_device *dev) { struct s3c24xx_led_platdata *pdata = dev->dev.platform_data; struct s3c24xx_gpio_led *led; int ret; led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL); if (led == NULL) { dev_err(&dev->dev, "No memory for device\n"); return -ENOMEM; } platform_set_drvdata(dev, led); led->cdev.brightness_set = s3c24xx_led_set; led->cdev.default_trigger = pdata->def_trigger; led->cdev.name = pdata->name; led->cdev.flags |= LED_CORE_SUSPENDRESUME; led->pdata = pdata; /* no point in having a pull-up if we are always driving */ if (pdata->flags & S3C24XX_LEDF_TRISTATE) { s3c2410_gpio_setpin(pdata->gpio, 0); s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_INPUT); } else { s3c2410_gpio_pullup(pdata->gpio, 0); s3c2410_gpio_setpin(pdata->gpio, 0); s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_OUTPUT); } /* register our new led device */ ret = led_classdev_register(&dev->dev, &led->cdev); if (ret < 0) { dev_err(&dev->dev, "led_classdev_register failed\n"); kfree(led); return ret; } return 0; }
利用struct,我們實現了一種面向對象的思想,實例化的結構體對象中,有描述這個對象的行為方式(函數),有描述對象特征值或者對象組成的變量(變量,結構體變量等)。
下面是設備結構體定義供參考:
struct platform_driver {
int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); int (*resume)(struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; };
/** * struct device_driver - The basic device driver structure * @name: Name of the device driver. * @bus: The bus which the device of this driver belongs to. * @owner: The module owner. * @mod_name: Used for built-in modules. * @suppress_bind_attrs: Disables bind/unbind via sysfs. * @of_match_table: The open firmware table. * @probe: Called to query the existence of a specific device, * whether this driver can work with it, and bind the driver * to a specific device. * @remove: Called when the device is removed from the system to * unbind a device from this driver. * @shutdown: Called at shut-down time to quiesce the device. * @suspend: Called to put the device to sleep mode. Usually to a * low power state. * @resume: Called to bring a device from sleep mode. * @groups: Default attributes that get created by the driver core * automatically. * @pm: Power management operations of the device which matched * this driver. * @p: Driver core's private data, no one other than the driver * core can touch this. * * The device driver-model tracks all of the drivers known to the system. * The main reason for this tracking is to enable the driver core to match * up drivers with new devices. Once drivers are known objects within the * system, however, a number of other things become possible. Device drivers * can export information and configuration variables that are independent * of any specific device. */ 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; };
...