最近学习了linux系统的总线驱动模型,在这就简单的讲一下自己对于其中的理解
在这个驱动模型中由几个重要的概念 :
总线 :这个"总线"不是我们通常所说的传输数据的总线,而是将设备和驱动联系起来的一个中间件,在这个总线上挂载了许多设备,在注册驱动模块的时候,它就会根据某种固定的匹配规则找到你想要操作的设备,然后进行操作.
设备 :这个"设备"是和总线相互联系的,等待驱动程序操控的
驱动 :由我们自己来写,实现某种设备的驱动.
讲了这么一些,理解起来也不是很准确,接下来来看代码:
/* 定义并初始化总线结构体,其中和我们相关的有这两个成员 */
static struct bus_type demobus = {
.name = "marathon", /* 总线的名称 */
.match = mara_match, /* 总线用于匹配的规则,为函数指针类型,指向我们定义的匹配函数 */
};
这个是我们写的总线匹配规则函数,需要注意的是,匹配成功返回1,否则返回0
传进来的参数就是之前我们所说的设备结构体对象和驱动结构体对象
static int mara_match(struct device *dev, struct device_driver *drv)
{
struct pridevice *pdev = container_of(dev, struct pridevice, device);
/*这里我们自定义的匹配规则是按照名字来匹配的*/
return !strncmp(pdev->name, drv->name, strlen(drv->name));
}
关于总线就讲上面一些,接下里讲关于设备结构的部分:
对总线结构体对象做外部声明
extern struct bus_type demobus;
定义我们自己的设备结构体,里面包含内核结构体对象struct device
struct pridevice {
struct device device; /*内核设备结构体对象*/
char *name; /*设备名*/
};
当驱动模型的设备和驱动由总线匹配成功后,内核会自动指向对应驱动模型的驱动对象
static struct pridevice demodev1 = {
.device = {
.init_name = "spring_1", /*设备名*/
.bus = &demobus, /*指向所关联的总线*/
.release = demo_release, /*移除设备对象时,调用该函数*/
struct device_driver driver; /*没有赋值,匹配成功之后自动指向驱动结构体对象*/
},
.name = "spring_1",
};
/*设备对象的注册和移除*/
device_register(&demodev1.device);
device_unregister(&demodev1.device);
接下来将关于驱动部分的代码:
对总线结构体对象做外部声明
extern struct bus_type demobus;
/*定义关于驱动的结构体,有这么几个成员需要我们注意*/
static struct device_driver demodrv1 = {
.name = "spring", /*驱动的名字*/
.bus = &demobus, /*此驱动对象所关联的总线*/
.probe = demo_probe, /*当设备和驱动由总线匹配成功,内核自动调用此probe函数,并将
匹配成功的设备对象的地址传递给此probe函数*/
.remove = demo_remove, /*移除驱动对象时调用*/
};
当总线的match函数返回1时,则由内核调用驱动对象的probe指针指向的 函数
static int demo_probe (struct device *dev)
{
设备对象地址指向我们所定义设备结构体内部的设备对象成员,根据此拿到整个结构体对象地址
struct pridevice *pdev = container_of(dev, struct pridevice, device);
匹配成功的设备结构体对象内部的驱动成员指向我们定义的驱动结构体对象
struct device_driver *pdrv = dev->driver;
printk("probe: %s driver do %s device...\n",pdrv->name, pdev->name);
return 0;
}
至此,整个匹配过程结束.有不对的地方还请批评和指正.