最近在学习总线、设备、驱动程序,编写总线设备驱动程序的时候,发现2.6.30.4内核中的struct device已经没有bus_id的成员了,发现了const char *init_name成员。但是,这个成员是不能直接用来设置和读取设备名的。通过查阅资料发现2.6.30.4的内核中对struct device属性的bus_id应经修改了,感觉这挺好的,最起码不会差生歧异。下面的2.6.30.4内核上所做的改变:
内核操作的方法为dev_name和dev_set_name。内核中的定义是:
1) dev_name
static inline const char *dev_name(const struct device *dev) { return kobject_name(&dev->kobj); }
2) dev_set_name
/** * dev_set_name - set a device name * @dev: device * @fmt: format string for the device's name */ int dev_set_name(struct device *dev, const char *fmt, ...) { va_list vargs; int err; va_start(vargs, fmt); err = kobject_set_name_vargs(&dev->kobj, fmt, vargs); va_end(vargs); return err; } EXPORT_SYMBOL_GPL(dev_set_name);
总线
总线是处理器和一个或多个设备之间的通道,在设备模型中, 所有的设备都通过总线相连, 甚至是内部的虚拟"platform "总线。总线可以相互插入。设备模型展示了总线和它们所控制的设备之间的实际连接。 在 Linux 设备模型中, 总线由 bus_type 结构表示, 定义在 <linux/device.h>,创建一条总线的实例 :
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> MODULE_AUTHOR("sjwangjinbao"); MODULE_LICENSE("Dual BSD/GPL"); static char *Version = "$Revision: 1.0 $"; static int my_match(struct device *dev, struct device_driver *driver) { return !strncmp(dev_name(dev) , driver->name, strlen(driver->name) ); } static void my_bus_release(struct device *dev) { printk("my bus release/n"); } struct device my_bus = { .release = my_bus_release }; struct bus_type my_bus_type = { .name = "my_bus", .match = my_match, }; EXPORT_SYMBOL(my_bus); EXPORT_SYMBOL(my_bus_type); /* * Export a simple attribute. */ static ssize_t show_bus_version(struct bus_type *bus, char *buf) { return snprintf(buf, PAGE_SIZE, "%s/n", Version); } static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL); static int __init my_bus_init(void) { int ret; /*注册总线*/ ret = bus_register(&my_bus_type); if (ret) { return ret; } /*创建属性文件*/ if (bus_create_file(&my_bus_type, &bus_attr_version)) { printk("Fail to create version attribute!/n"); } /*初始化总线设备*/ dev_set_name(&my_bus, "my_bus0"); /*注册总线设备*/ ret = device_register(&my_bus); if (ret) { printk("Fail to register device:my_bus!/n"); } return ret; } static void my_bus_exit(void) { device_unregister(&my_bus); bus_unregister(&my_bus_type); } module_init(my_bus_init); module_exit(my_bus_exit);
设备
在最底层, Linux 系统中的每个设备由一个 struct device 代表,内核创建一个设备的方实例:
#include <linux/device.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/string.h> MODULE_AUTHOR("sjwangjinbao"); MODULE_LICENSE("Dual BSD/GPL"); extern struct device my_bus; extern struct bus_type my_bus_type; static void my_dev_release(struct device *dev) { } struct device my_dev = { .bus = &my_bus_type, .parent = &my_bus, .release = my_dev_release, }; /* * Export a simple attribute. */ static ssize_t mydev_show(struct device *dev,struct device_attribute *attr, char *buf) { return sprintf(buf, "%s/n", "This is sjwangjinbao device!"); } static DEVICE_ATTR(dev, S_IRUGO, mydev_show, NULL); static int __init my_device_init(void) { int ret = 0; /*初始化设备*/ dev_set_name(&my_dev, "my_dev"); /*注册设备*/ device_register(&my_dev); /*创建属性文件*/ device_create_file(&my_dev, &dev_attr_dev); return ret; } static void my_device_exit(void) { device_unregister(&my_dev); } module_init(my_device_init); module_exit(my_device_exit);
驱动
在最底层, Linux 系统中的每个设备驱动程序由device_driver表示,在内核建立驱动文件测试程序代码如下
#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);