1、总线、设备和类之间的关系
2、总线(bus)、设备(device)、驱动(device_driver)
总线是处理器和设备之间的通道,在设备模型中, 所有的设备都通过总线相连, 甚至是内部的虚拟“platform”总线。 在 Linux 设备模型中, 总线由 bus_type结构表示, 定义在 <linux/device.h>
4、总线描述
struct bus_type {
const char *name; /*总线名称*/
struct bus_attribute *bus_attrs; /*总线属性*/
struct device_attribute *dev_attrs; /*设备属性*/
struct driver_attribute *drv_attrs; /*驱动属性*/
int (*match)(struct device *dev,struct device_driver *drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
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 (*suspend_late)(struct device *dev, pm_message_t state);
int (*resume_early)(struct device *dev);
int (*resume)(struct device *dev);
struct dev_pm_ops *pm;
struct bus_type_private *p;
};5、总线注册/删除
总线的注册使用:
bus_register(struct bus_type * bus);
若成功,新的总线将被添加进系统,并可在sysfs的 /sys/bus 下看到。
总线的删除使用:
void bus_unregister(struct bus_type *bus);
6、总线方法
int (*match)(struct device * dev,struct device_driver * drv)
当一个新设备或者驱动被添加到这个总线时,该方法被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零值。
int (*uevent)(struct device *dev, char **envp, int num_envp, char*buffer, int buffer_size)
在为用户空间产生热插拔事件之前,这个方法允许总线添加环境变量。
7、 总线属性总线属性由结构bus_attribute描述,定义如下:
struct bus_attribute {
struct attribute attr;
ssize_t (*show)(struct bus_type *, char * buf);
ssize_t (*store)(struct bus_type *, const char *buf, size_t count);
}
int bus_create_file(struct bus_type *bus, structbus_attribute *attr);
创建属性
void bus_remove_file(struct bus_type*bus,struct bus_attribute *attr);
删除属性
8、实例#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
MODULE_LICENSE("Dual BSD/GPL");
static char *Version = "Revision: 1.0";
/*
* Export a simple attribute.
*/
struct bus_type my_bus_type = {
.name = "my_bus",
};
EXPORT_SYMBOL(my_bus_type);
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(KERN_NOTICE "Fail to create version attribute!\n");
return ret;
}
static void __exit my_bus_exit(void)
{
bus_unregister(&my_bus_type);
}
module_init(my_bus_init);
module_exit(my_bus_exit);
Makefile
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
else
obj-m := bus.o
endif