16.总线设备驱动模型学习

            总线设备驱动模型学习

  

一、总线概述

  随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求也越来越高,2.4内核已经难以满足这些需求。为适应这种形势的需要,从Linux 2.6内核开始提供了全新的设备模型。

  总线:创建一条总线,跟按键一样,首先是描述总线结构,接着是注册总线,注销总线。总线设备,例如usb总线,上面会有很多类型的usb的驱动,例如鼠标、键盘.....等,当我们把之一的usb插上的时候,usb总线会把每个驱动遍历一遍,找到相应的驱动程序执行。

1.1总线描述

  在 Linux 内核中, 总线由 bus_type 结构表示, 定义在 <linux/device.h>

1 struct bus_type{
2     const char *name; /*总线名称*/
3     int (*match) (struct device *dev, struct
4     device_driver *drv); /*驱动与设备的匹配函数*/
5     …
6 }

  int (*match)(struct device * dev, struct device_driver * drv)当一个新设备或者新驱动被添加到这个总线时,该函数被调用。用于判断指定的驱动程序是否能处理指定的设备。若可以,则返回非零。

1.2总线注册于注销

总线的注册使用:
  bus_register(struct bus_type *bus)
  若成功,新的总线将被添加进系统,并可在/sys/bus 下看到相应的目录。

总线的注销使用:
  void bus_unregister(struct bus_type *bus)

创建一条总线:

 1 #include <linux/init.h>
 2 #include <linux/module.h>
 3 #include <linux/kernel.h>
 4 #include <linux/device.h>
 5 MODULE_LICENSE("GPL");
 6 int my_match(struct device *dev,struct device_driver *drv)
 7 {
 8     return 0;
 9 }
10
11 struct bus_type my_bus_type = {
12     .name = "my_bus",
13     .match = my_match,
14 };
15
16 EXPORT_SYMBOL(my_bus_type);//变量输出
17
18 int my_bus_init(void)
19 {
20     int ret;
21     ret = bus_register(&my_bus_type);
22     return ret;
23 }
24
25 void my_bus_exit(void)
26 {
27     bus_unregister(&my_bus_type);
28 }
29
30 module_init(my_bus_init);
31 module_exit(my_bus_exit);

控制台运行:

  

二、总线驱动

2.1总线设备驱动描述结构

  在 Linux内核中, 驱动由 device_driver结构表示。

1 struct device_driver{
2 {
3   const char *name; /*驱动名称*/
4   struct bus_type *bus; /*驱动程序所在的总线*/
5   int (*probe) (struct device *dev);
6   …
7 }

  prode函数,当我们有设备加到总线的时候,当设备与总线的某个借口相匹配的时候,系统就会调用prode函数。对我的设备进行相应的初始化。

2.2驱动的注册于注销

驱动的注册:
  int driver_register(struct device_driver *drv)
驱动的注销使用:
  void driver_unregister(struct device_driver *drv)

总线设备驱动程序:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>

MODULE_LICENSE("GPL");
extern struct bus_type my_bus_type;

int my_probe (struct device *dev)
{
    printk(KERN_EMERG"driver found the device it can handle!\n");
     //如果是实际应用的驱动,这里会做很多的硬件初始化操作
    return 0;
}

struct device_driver my_driver = {
    .name = "my_dev",
    .bus = &my_bus_type,   /*驱动是属于哪一条总线的。这里来自总线驱动程序,所以总线的代码
                                要有EXPORT_SYMBOL符号导出标志*/
    .probe = my_probe,
};

int my_driver_init(void)
{
    int ret;
    ret = driver_register(&my_driver);
    return 0;
}

void my_driver_exit(void)
{
    driver_unregister(&my_driver);
}

module_init(my_driver_init);
module_exit(my_driver_exit);

  

  上面的目录/sys/bus/存的是系统总线的各类接口,可以看到了创建的mybus总线,进去,打开驱动drivers的目录,里面有创建的驱动my_dev,驱动挂载成功了。

三、设备

3.1设备描述结构

  在 Linux内核中, 设备由struct device结构表示。

1 struct device{
2 {
3   const char*init_name; /*设备的名字*/
4   struct bus_type *bus; /*设备所在的总线*/
5   …
6 }

3.2设备注销与注册

设备的注册使用如下函数
  int device_register(struct device *dev)
设备的注销使用:
  void device_unregister(struct device *dev)

设备程序如下:

 1 #include <linux/device.h>
 2 #include <linux/module.h>
 3 #include <linux/kernel.h>
 4 #include <linux/init.h>
 5
 6 MODULE_LICENSE("GPL");
 7
 8 extern struct bus_type my_bus_type;
 9
10 struct device my_dev=
11 {
12     .init_name = "my_dev",
13     .bus = &my_bus_type,
14 };
15
16 int my_device_init(void)
17 {
18     int ret;
19     ret = device_register(&my_dev);
20     return 0;
21 }
22
23 void my_device_exit(void)
24 {
25     device_unregister(&my_dev);
26 }
27
28 module_init(my_device_init);
29 module_exit(my_device_exit);

四、编译运行

Makefile文件如下:

obj-m := driver.o bus.o device.o
KDIR :=/home/kernel/kernel/linux-ok6410
all:
    make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
clean:
    rm -f *.ko *.o *.order *.symvers *.mod.c *~

将我们的总线程序修改为:

1 int my_match(struct device *dev,struct device_driver *drv)
2 {
3      return !strncmp(dev->init_name,drv->name,strlen(drv->name));   //名字匹配
4
5 }

运行结果如下:

分析错误提醒:

  出现了空指针:是在strncmp里出现了空指针,这个空指针是init_name;但是我们在我的device.c里已经.init_name="my_dev",为什么还是空指针呢?接下来看内核代码:

首先是找device_register:

  

进入上面的device_add函数:

  

  上面的代码就是把不为空的init_name,赋值给dev_set_name,然后自身的值变为NULL。所以,我们的程序出现空指针的原因。这个值被赋值到了成员kobj.name:

因此我们将bus程序修改为:

1 int my_match(struct device *dev,struct device_driver *drv)
2 {
3     // return !strncmp(dev->init_name,drv->name,strlen(drv->name));   //名字匹配
4     return !strncmp(dev->kobj.name,drv->name,strlen(drv->name));
5 }

编译运行:

  

  当然也可以先执行设备程序在执行驱动程序,但是总线是必须先创建的

时间: 2024-10-08 10:16:47

16.总线设备驱动模型学习的相关文章

20150225 IMX257 总线设备驱动模型编程之总线篇

20150225 IMX257 总线设备驱动模型编程之总线篇 2015-02-25 19:40 李海沿 从现在开始,我们开始来实现 总线-设备-驱动模型中的总线.. 我们这个程序的目标是在 sysfs文件系统的/sys/bus/ 目录下面建立一个文件夹. 一.总线介绍 1. 总线数据结构bus_type struct bus_type 结构体的定义如下: struct bus_type { const char *name; --总线名 struct bus_attribute *bus_att

20150226 IMX257 总线设备驱动模型编程之驱动篇

20150226 IMX257 总线设备驱动模型编程之驱动篇 2015-02-26 11:42 李海沿 前面我们已经实现了 总线和设备 的驱动程序,接下来我们的任务就是 实现 驱动 了 地址:http://www.cnblogs.com/lihaiyan/p/4301079.html http://www.cnblogs.com/lihaiyan/p/4301072.html 在实现驱动程序之前,我们来想两个问题: 一.问题分析 1.什么时候驱动程序会在总线上找它可以处理的设备? 在driver

20150226 IMX257 总线设备驱动模型编程之平台总线设备platform

20150226 IMX257 总线设备驱动模型编程之平台总线设备platform 2015-02-26 李海沿 前面我们实现了总线设备驱动模型,下面我们来了解一下平台总线,平台设备驱动 分为平台设备和平台驱动两种,和前面所说的设备驱动差不多 platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver.Linux 2.6的设备驱动模型中,把I2C.RTC.LCD等都归纳为platform_device. 一.平台设备介绍 1. p

20150226 IMX257 总线设备驱动模型编程之设备篇

20150226 IMX257 总线设备驱动模型编程之设备篇 2015-02-26 李海沿 前面我们呢实现了总线-设备-驱动模型中的总线,自然,我们的目标就是在我们建立的总线下面创建一个设备. http://www.cnblogs.com/lihaiyan/p/4301072.html 一.程序分析 1. 包含总线 既然我们的设备在总线上,自然我们既要包含总线了 如图所示,使用外部声明将我们的总线的结构体包含进来 2. 定义设备结构体 父目录为 my_bus 3. 定义属性文件结构体 属性文件结

linux总线设备驱动模型

本篇文章通过平台总线设备模型为例,讲解总线设备驱动模型: platform_device_register的作用: 1.把device放入bus的device链表 2.从bus的driver链表中取出每一个driver,用bus的match函数判断driver能否支持这个device 3.若可以支持,调用driver的probe函数 platform_driver_register的作用: 1.将driver放入bus的driver链表 2.从bus的device链表中取出每一个device,用

8.总线设备驱动模型

总线设备驱动模型 总线:创建一条总线,跟我们前面的按键一样,首先是描述总线结构,接着是注册总线,注销总线.总线设备,例如usb总线,上面会有很多类型的usb的驱动,例如鼠标.键盘.....等,当我们把之一的usb插上的时候,usb总线会把每个驱动遍历一遍,找到相应的驱动程序执行. 接下来用bus.c创建一条总线. #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #in

linux嵌入式驱动-总线设备驱动模型

一个农夫想要合理的理财,他给你未来N天的每天支出(1<=N<=100000), 并计划把这N天分成M个部分(1 <=M <=N)(每个部分的天数是连续的),要求求出这些部分里花费最和最大值最小,输出这个最大值. 100 400 300 100 500 101 400 可以这么划分(100 400) (300 100) (500) (101)(400) ,五个分组里最大值是500,这个划是最佳的了,因为在其他划分里肯定有部分是大于500的,如(100) (400 300) (100

总线设备驱动模型【转】

本文转载自:http://blog.csdn.net/coding__madman/article/details/51428400 总线驱动设备模型: 1. 总线设备驱动模型概述 随着技术的不断进步,系统的拓扑结构也越来越复杂,对热插拔,跨平台移植性的要求也越来越高,2.4内核已经难以满足这些需求,为适应这宗形势的需求,从linux2.6内核开始提供了全新的设备模型 2. 总线 2.1 描述结构 2.2 注册 2.3 注销 void  bus_unregister(struct  bus_ty

总线设备驱动模型

一.总线模型(转自国嵌论坛) 1.随着技术的进步,对热插拔的要求以及可移植性的要求越来越高,从Linux2.4开始虽然有了模型但是正式提出是在Linux2.6. 2.关键词是总线,驱动,设备 3.总线能够感知设备的插拔: (1)插入新设备的时候知道有设备插入,那么就去总线上已有的驱动里面查找能够处理该新设备的驱动,一旦匹配,该驱动就有了该设备的控制权 (2)拔出的时候,总线也能感知,并且告诉相应的驱动从而使得驱动能够处理拔出事件二.总线 1.描述结构 linux内核中总线由bus_type结构描