在linux系统的fsysfs中创设总线以及
发布时间: 2012-09-25 09:55:59 作者: rapoo
在linux系统的fsysfs中创建总线,以及为总线增加设备和驱动
注册总线三步曲:
- 注册总线
bus_register(&my_bus_type);
- 创建属性文件
bus_create_file(&my_bus_type, &bus_attr_version);
- 注册总线设备
device_register(&my_bus);总线由struct bus_type结构来表示,如第一步的my_bus_type, 定义在<linux/device.h>中该结构管理着总线的名字,总线设备匹配,总线内设备的热插拔等事情,如struct bus_type my_bus_type = {.name = "my_bus",.match = my_match,.hotplug = my_hotplug,};总线的名字就是显示在/sys/bus/目录下的名字,如上面的my_bus。当总线上有新设备或新驱动被添加时,会一次或多次调用match函数。 在为用户空间产生热插拔事件前,可以通过hotplug函数添加环境变量,这个工作不是必要的。总线属性由 struct bus_attribute结构来描述,在代码中使用#define BUS_ATTR(_name, _mode, _show, _store)来创建和初始化。struct bus_attribute {struct attribute attr;ssize_t (*show)(struct bus_type *bus, char *buf);ssize_t (*store)(struct bus_type *bus, const char *buf, size_t count);};比如要在my_bus目录下定义一个属性文件version,代表bus的版本,则可以这样写: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);if (bus_create_file(&my_bus_type, &bus_attr_version))printk(KERN_NOTICE "Fail to create version attribute!\n");每一个总线本身也是一个设备,所以也需要注册总线设备,在linux2.6.32及以后的内核中,总线设备的名字由init_name来表示,以及dev_name() 和 dev_set_name() 来获取和设置设备名称。由于总线设备是顶层总线,所以其parent和bus成员是NULL,而release方法不做任何实质性的工作。总线创建成功以后,在新的总线目录下有devices和drivers目录,这两个目录分别包含总线下的设备和设备驱动。在总线下创建设备
- 初始化设备
dev_set_name(&my_dev, "my_dev");...
- 注册设备
device_register(&my_dev);
- 创建属性文件
device_create_file(&my_dev, &dev_attr_dev);如果需要把一个设备注册到某个总线之下,则需要把总线相关的信息与该设备关联起来,这是通过定义设备的父设备和总线的bus_type,设备的父设备使用总线名称来表示。如总线的名称是my_bus,总线的bus_type是my_bus_type。则:struct device my_dev = {.bus = &my_bus_type,.parent = &my_bus,.release = my_dev_release,};在总线下创建驱动
- 注册驱动
driver_register(&my_driver);
- 创建属性文件
driver_create_file(&my_driver, &driver_attr_drv);驱动程序由以下结构来定义struct device_driver{char *name; /*驱动的名字*/struct bus_type *bus; /*属于哪个总线*/struct kobject kobj;struct list_head devices;int (* probe) (struct device *dev); /*驱动的probe*/int (* remove) (struct device *dev);/*驱动的remove*/void (* shutdown) ( struct device *dev);/*当关机时,调用该函数*/…};驱动与总线的所属关系是通过 *bus联系起来的,name是驱动的名称,总线的match方法就是通过设备驱动名称与设备名称比较来实现的。如在my_bus总线下增加一个名称为my_dev的驱动,则该结构应该包括以下部分:struct device_driver my_driver = {.name = "my_dev",.bus = &my_bus_type,.probe = my_probe,.remove = my_remove,};