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

Linux设备与驱动学习笔记(概述)

2016-03-09 19:06 363 查看
由于在下能力相当有限,有不当之处,还望大家批评指正^_^

本文基于Linux内核2.6.32

一、宏观架构

在内核中,大量的驱动与设备(但不是全部),都按总线进行分类管理。

例如,凡是pci设备或pci设备的驱动,都归到pci总线下管理。

1. 从sys文件系统感受这种架构。

/sys/bus/目录下列出了各种总线类型,像pci、i2c、usb、platform等。

我们以pci总线为例,看看相关概念。

/sys/bus/pci/devices/目录下则则列出了所有系统中存在的所有pci设备(不管有没有安装对应的驱动程序)的名称,pci设备的名称即pci地址(即
"域:pci总线号:槽位号:功能号")。下面的示例输出,限于篇幅,只列出了几个设备作为样例。

[root@211-157-CGSLV5 char]# ls /sys/bus/pci/devices/

0000:00:00.0 0000:03:00.0 0000:06:12.7 0000:06:16.3

/sys/bus/pci/drivers目录下则列出了所有已加载的所有pci设备的驱动。

下面的示例输出,列出了pci设备驱动ixgbe(一款网卡驱动程序),以及当前接管了哪些设备(0000:06:00.0和0000:06:00.1)。

[root@211-157-CGSLV5 char]# ls /sys/bus/pci/drivers/ixgbe

0000:06:00.0 0000:06:00.1 bind module new_id remove_id uevent unbind

示例输出中还有一些别的文件,像bind用来指定某个pci设备由此驱动接管,unbind则起相反的作用。通常,一个驱动都有自己支持的设备型号的列表。new_id用于动态增加此驱动可以接管的设备型号,remove_id则起相反作用。

【注】

pci设备的名称,是通过如下方式设置的

dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),

dev->bus->number, PCI_SLOT(dev->devfn),

PCI_FUNC(dev->devfn));

而其他类型的设备,命名方式也名异。下面列出了其他几种设备的命名方式

(i) isa

dev_set_name(&isa_dev->dev, "%s.%u",

isa_driver->driver.name, id);

(ii)platform

if (pdev->id != -1)

dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);

else

dev_set_name(&pdev->dev, "%s", pdev->name);

(iii)I2C

dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),

client->addr);

【注】

有时候,可能会存在多个驱动,都可以驱动某一个设备的情况。

这时候,用户可以执行将设备与驱动进行绑定或解除绑定的操作。

将设备与驱动绑定的方法为:

echo dev_name > /sys/bus/bus_type/drivers/driver_name/bind

将设备与驱动解除绑定的方法为:

echo dev_name > /sys/bus/bus_type/drivers/driver_name/unbind

例如,将名称为0000:06:00.1的pci设备与名为ixgbe的驱动绑定,则命令如下:
echo 0000:06:00.1
> /sys/bus/pci/drivers/ixgbe/bind

echo命令执行后,由driver_bind/driver_unbind函数执行具体的绑定与解绑。

这两个函数对应于sys文件系统的store操作。

当然,除了pci总线,还有别的总线类型。

不同类型的总线,有着不同的原理与概念。

下面列出了若干不同类型总线的设备,可以看到其命名风格的不同。

[root@211-157-CGSLV5 char]# ls /sys/bus/i2c/devices/

2-007c i2c-0 i2c-1 i2c-2 i2c-3

[root@211-157-CGSLV5 char]# ls /sys/bus/usb/devices/

1-0:1.0 1-1 1-1:1.0 1-1.3 1-1.3:1.0 1-1.3:1.1 2-0:1.0 2-1 2-1:1.0 usb1 usb2

[root@211-157-CGSLV5
char]# ls /sys/bus/platform/devices/

alarmtimer coretemp.1 GHES.0 gpio_ich iTCO_wdt pcspkr

coretemp.0 Fixed MDIO bus.0 GHES.1 ipmi_bmc.3060.8 microcode serial8250



2. 从源代码中感受这种架构。
设备驱动方面的核心代码,位于drivers/base目录下。core.c是设备管理的核心文件,driver.c是驱动管理的核心文件,bus.c是总线处理的核心文件。我们可以以他们为线索,看出不同模块之间的调用关系,同时也能看出内核在管理设备与驱动方面的精妙设计理念。
在看代码之前,先来聊聊设备、驱动、总线之间的关系,同时引出一些内核中的重要数据结构。首先说说设备。不管是什么奇奇怪怪的设备,它毕竟都是一个设备。所以,在这个层次上,可以将一切设备都归纳到设备这个集合中去管理。就像动物一样,不管是人,还是猪马牛羊,站在动物这个层次上,都可以归属到动物这个类别中去。
在内核中,用于表示一个设备的数据结构是 struct device。

再来说说驱动。同理,一切驱动都是驱动,自然也是统一管理。

内核中,表示一个驱动的数据结构是 struct
device_driver。

好了,现在已经有了设备与驱动的表示方法。但是,这是站在最高层次上做出的概念抽象。

不同类型总线的设备,其标识方法也各有不同。

实际上,内核源码中也为此定义了不同类型的结构来标识之。

例如,struct platform_device_id用于标识platform设备,struct pci_device_id用于标识pci设备。

未完...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: