您的位置:首页 > 运维架构 > Linux

在linux系统的fsysfs中创建总线,以及为总线增加设备和驱动

2012-09-20 17:07 405 查看
注册总线三步曲:

注册总线

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,
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: