linux总线、设备和设备驱动的关系
总线是处理器和一个或多个设备之间的通道,在设备模型中,所有的设备都通过总线相连,甚至是内部的虚拟"platform"总线。可以通过ls -l /sys/bus看到系统加载的所有总线。
drwxr-xr-x root root 1970-01-01 00:02 platform
drwxr-xr-x root root 1970-01-01 00:02 spi
drwxr-xr-x root root 1970-01-01 00:02 scsi
drwxr-xr-x root root 1970-01-01 00:02 usb
drwxr-xr-x root root 1970-01-01 00:02 serio
drwxr-xr-x root root 1970-01-01 00:02 i2c
drwxr-xr-x root root 1970-01-01 00:02 mmc
drwxr-xr-x root root 1970-01-01 00:02 sdio
drwxr-xr-x root root 1970-01-01 00:02 ac97
总线可以相互插入。设备模型展示了总线和它们所控制的设备之间的实际连接。在Linux 设备模型中,总线由bus_type 结构表示,定义在 :
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 pm_ext_ops *pm;
struct bus_type_private *p;
};
1,总线的注册和删除,总线的主要注册步骤:
(1)申明和初始化bus_type 结构体。只有很少的bus_type 成员需要初始化,大部分都由设备模型核心控制。但必须为总线指定名字及一些必要的方法。例如:
struct bus_type ldd_bus_type = {
.name = "ldd",
.match = ldd_match,
.uevent = ldd_uevent,
};
(2)调用bus_register函数注册总线。int bus_register(struct bus_type *bus),该调用可能失败,所以必须始终检查返回值。
ret = bus_register(&ldd_bus_type);
if (ret)
return ret;
若成功,新的总线子系统将被添加进系统,之后可以向总线添加设备。当必须从系统中删除一个总线时,调用:
void bus_unregister(struct bus_type *bus);
2,总线方法
在 bus_type 结构中定义了许多方法,它们允许总线核心作为设备核心与单独的驱动程序之间提供服务的中介,主要介绍以下两个方法: int (*match)(struct device * dev, struct device_driver * drv);
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
对设备和驱动的迭代:若要编写总线层代码,可能不得不对所有已经注册到总线的设备或驱动进行一些迭代操作,这可能需要仔细研究嵌入到 bus_type 结构中的其他数据结构,但最好使用内核提供的辅助函数:
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *));
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *));
3,总线属性
几乎Linux 设备模型中的每一层都提供添加属性的函数,总线层也不例外。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);
};
内核提供了一个宏在编译时创建和初始化bus_attribute 结构:
BUS_ATTR(_name,_mode,_show,_store)
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr);
void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr);
例如创建一个包含源码版本号简单属性方法如下:
static ssize_t show_bus_version(struct bus_type *bus, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%s", Version);
}
static BUS_ATTR(version, S_IRUGO, show_bus_version, NULL); //得到bus_attr_version
if (bus_create_file(&ldd_bus_type, &bus_attr_version))
printk(KERN_NOTICE "Unable to create version attribute");
之二:device
在最底层,Linux 系统中的每个设备由一
linux总线设备设备驱 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)