Linux 内核驱动结构嵌入
如同大部分驱动核心结构的情形,device_driver 结构常常被发现嵌到一个更高级的,总 线特定的结构. lddbus 子系统不会和这样的趋势相反,因此它已定义了它自己的 ldd_driver 结构: ? struct ldd_driver { char *version; struct module *module; struct device_driver driver; struct driver_attribute version_attr; }; #define to_ldd_driver(drv) container_of(drv,struct ldd_driver,driver); ? 这里,我们要求每个驱动提供特定当前软件版本,并且 lddbus 输出这个版本字串为它知 道的每个驱动. 总线特定的驱动注册函数是: ? int register_ldd_driver(struct ldd_driver *driver) { ? int ret; driver->driver.bus = &ldd_bus_type; ret = driver_register(&driver->driver); if (ret) return ret; driver->version_attr.attr.name = "version"; driver->version_attr.attr.owner = driver->module; driver->version_attr.attr.mode = S_IRUGO; driver->version_attr.show = show_version; driver->version_attr.store = NULL; return driver_create_file(&driver->driver,&driver->version_attr); } ? 这个函数的第一部分只注册低级的 device_driver 结构到核心; 剩下的建立版本属性. 因为这个属性在运行时被创建,我们不能使用 DRIVER_ATTR 宏; 反之, ? driver_attribute 结构必须手工填充. 注意我们设定属性的拥有者为驱动模块,不是 lddbus 模块; 这样做的理由是可以在为这个属性的 show 函数的实现中见到: ? static ssize_t show_version(struct device_driver *driver,char *buf) { struct ldd_driver *ldriver = to_ldd_driver(driver); sprintf(buf,"%sn",ldriver->version); return strlen(buf); } ? 有人可能认为属性拥有者应当是 lddbus 模块,因为实现这个属性的函数在那里定义. 这 个函数,但是,是使用驱动自身所创建的 ldd_driver 结构. 如果那个结构在一个用户空 间进程试图读取版本号时要消失,事情会变得麻烦. 指定驱动模块作为属性的拥有者阻止 了模块被卸载,在用户空间保持属性文件打开时. 因为每个驱动模块创建一个对 lddbus 模块的引用,我们能确信 lddbus 不会在一个不合适的时间被卸载. ? 为完整起见,sculld 创建它的 ldd_driver 结构如下: ? static struct ldd_driver sculld_driver = { .version = "$Revision: 1.1 $",.module = THIS_MODULE,.driver = { .name = "sculld",},}; ? 一个简单的对 register_ldd_driver 的调用添加它到系统中. 一旦完成初始化,驱动信 息可在 sysfs 中见到: ? $ tree /sys/bus/ldd/drivers /sys/bus/ldd/drivers `-- sculld |-- sculld0 -> ../../../../devices/ldd0/sculld0 |-- sculld1 -> ../../../../devices/ldd0/sculld1 |-- sculld2 -> ../../../../devices/ldd0/sculld2 |-- sculld3 -> ../../../../devices/ldd0/sculld3 ? [46] 这个总线的逻辑名子,当然,应当是"sbus",但是这个名子已经被一个真实的,物理总 线采用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |