Linux Kernel in a Nutshell 笔记(四)

7.Customizing a Kernel

判断系统需要哪些驱动的最简单的办法就是查找发行版本内核的配置;或者可以查找 /proc/ 下面的 config.gz 文件:
$ ll /proc/config.gz
-r–r–r– 1 root root 31089 May  1 20:40 /proc/config.gz
$ cp /proc/config.gz ~/linux
$ cd ~/linux
$ gunzip -dv config.gz

解压之后将其复制到 kernel 的顶层目录,然后就可以参照之前的步骤编译了。当然不是每个系统都有 config.gz 文件,这个要看当初该内核的配置文件里面有没有下面这两行:
$ cat /boot/config-$(uname -r) | grep -i ikconfig
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y

如果没有的话,就不会在 /proc/ 下面发现 config.gz 文件了,可以在编译内核的时候加入下面的选项:
General setup —>
<*> Kernel .config support
[*] Enable access to .config through /proc/config.gz

模块大多可以在 /sys/ 目录下找到,该目录是一个名叫 sysfs 的虚拟文件系统,跟 /proc/ 类似。下面以找网络驱动为例。

找到所有的网络接口:
jaseywang@ThinkPad:/sys/class/net# ll /sys/class/net/
total 0
lrwxrwxrwx 1 root root 0 2012-05-01 23:54 eth0 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/net/eth0/
lrwxrwxrwx 1 root root 0 2012-05-01 23:54 eth1 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.1/net/eth1/
lrwxrwxrwx 1 root root 0 2012-05-01 23:54 eth2 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.0/net/eth2/
lrwxrwxrwx 1 root root 0 2012-05-01 23:54 eth3 -> ../../devices/pci0000:00/0000:00:03.0/0000:02:00.1/net/eth3/
lrwxrwxrwx 1 root root 0 2012-05-01 23:54 eth4 -> ../../devices/pci0000:00/0000:00:09.0/0000:05:00.0/net/eth4/
lrwxrwxrwx 1 root root 0 2012-05-01 23:54 eth5 -> ../../devices/pci0000:00/0000:00:09.0/0000:05:00.1/net/eth5/
lrwxrwxrwx 1 root root 0 2012-05-01 17:09 lo -> ../../devices/virtual/net/lo/

找到目前在用的接口:
jaseywang@ThinkPad:/sys/class/net# ifconfig  -a | head
eth0      Link encap:Ethernet  HWaddr d4:be:d9:ed:64:9d 
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:36 Memory:d2000000-d2012800
eth1      Link encap:Ethernet  HWaddr d4:be:d9:ed:64:9f 
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:48 Memory:d4000000-d4012800

eth2      Link encap:Ethernet  HWaddr d4:be:d9:ed:64:a1 
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:32 Memory:d6000000-d6012800
eth3      Link encap:Ethernet  HWaddr d4:be:d9:ed:64:a3 
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:42 Memory:d8000000-d8012800

eth4      Link encap:Ethernet  HWaddr 00:10:18:be:6f:64 
          inet addr:10.18.10.50  Bcast:10.18.10.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:36191509 errors:0 dropped:0 overruns:0 frame:0
          TX packets:520263 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:6240615358 (6.2 GB)  TX bytes:44789837 (44.7 MB)
          Interrupt:40 Memory:da000000-da012800

eth5      Link encap:Ethernet  HWaddr 00:10:18:be:6f:66 
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:50 Memory:dc000000-dc012800

lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:967 errors:0 dropped:0 overruns:0 frame:0
          TX packets:967 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:48692 (48.6 KB)  TX bytes:48692 (48.6 KB)

找到控制 eth4 的模块/驱动:
root@ThinkPad:/sys/class/net/eth4/device/driver# basename  `readlink  /sys/class/net/eth4/device/driver/module`
bnx2

去源码文件中找 bnx2 有关的信息:
jaseywang@ThinkPad:~/linux/linux-2.6.32.28$ find -type f -name Makefile  | xargs grep bnx2
./firmware/Makefile:fw-shipped-$(CONFIG_BNX2X) += bnx2x-e1-5.0.21.0.fw bnx2x-e1h-5.0.21.0.fw
./firmware/Makefile:fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-5.0.0.j3.fw \
./firmware/Makefile:                         bnx2/bnx2-rv2p-09-5.0.0.j3.fw \
./firmware/Makefile:                         bnx2/bnx2-rv2p-09ax-5.0.0.j3.fw \
./firmware/Makefile:                         bnx2/bnx2-mips-06-5.0.0.j3.fw \
./firmware/Makefile:                         bnx2/bnx2-rv2p-06-5.0.0.j3.fw
./drivers/scsi/Makefile:obj-$(CONFIG_SCSI_BNX2_ISCSI)   += libiscsi.o bnx2i/
./drivers/scsi/bnx2i/Makefile:bnx2i-y := bnx2i_init.o bnx2i_hwi.o bnx2i_iscsi.o bnx2i_sysfs.o
./drivers/scsi/bnx2i/Makefile:obj-$(CONFIG_SCSI_BNX2_ISCSI) += bnx2i.o
./drivers/net/Makefile:obj-$(CONFIG_BNX2) += bnx2.o
./drivers/net/Makefile:obj-$(CONFIG_BNX2X) += bnx2x.o
./drivers/net/Makefile:bnx2x-objs := bnx2x_main.o bnx2x_link.o

关键需要找到以 CONFIG_ 开头的关键字,可以发现,我们需要找的是 CONFIG_BNX2(CONFIG_BNX2X 是 10G 网卡的驱动),接着:
jaseywang@ThinkPad:~/linux/linux-2.6.32.28$ make menuconfig

跳出修改内核配置的 menu,输入 "/" 进入查找页面,接着查找 "BNX2",可以发现第一个就是我们需要找的驱动,接着按照上面的路径提示就可以找到跟系统匹配的网卡驱动了。

再举一例,找 USB 驱动:
[jaseywang@TP linux-2.6.32.59]$ ls /sys/class/tty/ | grep USB
ttyUSB0
ttyUSB1
ttyUSB2
[jaseywang@TP linux-2.6.32.59]$ basename   `readlink /sys/class/tty/ttyUSB0/device/driver/module`
option
[jaseywang@TP linux-2.6.32.59]$ find -type f -name Makefile | xargs grep option | grep CONFIG_ | head
./drivers/usb/serial/Makefile:obj-$(CONFIG_USB_SERIAL_OPTION)                   += option.o
./Makefile:KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
./Makefile:# kernel config option CONFIG_LOCALVERSION_AUTO is selected.  Also, at the
./arch/arm/Makefile:arch-$(CONFIG_CPU_32v7)             :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a)
./arch/arm/Makefile:arch-$(CONFIG_CPU_32v6)             :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
./arch/arm/Makefile:arch-$(CONFIG_CPU_32v6K)    :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
./arch/arm/Makefile:arch-$(CONFIG_CPU_32v5)             :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
./arch/arm/Makefile:tune-$(CONFIG_CPU_ARM946E)  :=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
./arch/arm/Makefile:tune-$(CONFIG_CPU_XSCALE)   :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
./arch/arm/Makefile:tune-$(CONFIG_CPU_XSC3)             :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
可以看到驱动的名字是 CONFIG_USB_SERIAL_OPTION,接下来 make menuconfig,然后搜索 “USB_SERIAL_OPTION” 就能找到对应的驱动了:
Symbol: USB_SERIAL_OPTION [=n]
Prompt: USB driver for GSM and CDMA modems                
  Defined at drivers/usb/serial/Kconfig:568               
  Depends on: USB_SUPPORT [=y] && USB_SERIAL [=n]         
  Location:                                               
    -> Device Drivers                                     
      -> USB support (USB_SUPPORT [=y])                   
        -> USB Serial Converter support (USB_SERIAL [=n])

小结一下,查找驱动的步骤:
1.去 /sys/ 找驱动,网络相关的到 /sys/class/net/ 下面,tty 设备到 /sys/class/tty/ 下面,其余的设备根据设备类型在 /sys/class/ 其他的目录里面
2.跟进,找到驱动名称:
$ basename `readlink /sys/class/class_name/device_name/deivce/driver/module`
3.到内核源码树里面找到配置对应的选项,以 CONFIG_ 开头的:
$ find -type -f -name Makefile  | xargs grep module_name
4.make menuconfig 之后查找,将其选中,编译进内核或者以模块的形式出现

下面这个脚本用来寻找系统中用到的所有驱动,首先 cat 出 /sys/ 中名叫 modalias 文件的内容,该文件里面包含模块的 alias,他会告诉 modprobe 命令,哪些模块需要加载以支持某个设备,模块的 alias 由 device manufacturer, ID, class type 一起其他的一些特殊识别符号组成:

#!/bin/bash
for i in $(find /sys/ -name modalias -exec cat {} \;); do
        modprobe –config /dev/null –show-depends $i;
done  | rev | cut -d '/' -f 1 | rev | sort -u

jaseywang@ThinkPad:~$ ./modules.sh | tee module
jaseywang@ThinkPad:~$ cat module

bnx2.ko
dcdbas.ko
enclosure.ko
evbug.ko
hid.ko
iTCO_vendor_support.ko
iTCO_wdt.ko
joydev.ko
megaraid_sas.ko
pcspkr.ko
power_meter.ko
psmouse.ko
serio_raw.ko
ses.ko
shpchp.ko
snd.ko
snd-page-alloc.ko
snd-pcm.ko
snd-pcsp.ko
snd-timer.ko
soundcore.ko
usbhid.ko

在执行过程中,可能出现打印出下面的错误,表明没有找到设备对应的驱动,暂时可以忽略:
FATAL: Module pci:v00008086d00003422sv00000000sd00000000bc08sc00i00 not found.
FATAL: Module pci:v00008086d00003423sv00000000sd00000000bc08sc00i00 not found.
FATAL: Module pci:v00008086d00002937sv00001028sd00000236bc0Csc03i00 not found.
FATAL: Module usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00 not found.
FATAL: Module pci:v00008086d00002938sv00001028sd00000236bc0Csc03i00 not found.
FATAL: Module usb:v1D6Bp0001d0206dc09dsc00dp00ic09isc00ip00 not found.
FATAL: Module pci:v00008086d0000293Csv00001028sd00000236bc0Csc03i20 not found.
FATAL: Module usb:v1D6Bp0002d0206dc09dsc00dp00ic09isc00ip00 not found.
FATAL: Module usb:v0424p2514d0000dc09dsc00dp02ic09isc00ip02 not found.
FATAL: Module scsi:t_0x00 not found.

有时候新增了一个设备,但是不知道是否有驱动支持,最简单的办法是将所有跟这个设备型号相关的都以模块的形式编译起来,然后系统启动时,由 udev 来匹配最佳的模块,接着,使用之前说的那些步骤就可以精确定位到使用到的模块。当然,如果不想将所有的模块都编译进去,可以根据下面的方式走,下面涉及最常使用的两种设备:PCI 以及 USB。

所有的 PCI 设备都是由 vender ID 和 device ID 组成,二者组成一个唯一的标示。我们以网卡为例,首先通过 lspci 找到网卡的 bus ID:
jaseywang@ThinkPad:~$ lspci  | grep -i eth
01:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
01:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
02:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
02:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
05:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)
05:00.1 Ethernet controller: Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet (rev 20)

上面列出的 01:00.0 等就是 PCI 的 bus ID,我们需要通过该 ID 找出更多的信息:
jaseywang@ThinkPad:/sys/bus/pci/devices$ pwd
/sys/bus/pci/devices
jaseywang@ThinkPad:/sys/bus/pci/devices$ ls
0000:00:00.0  0000:00:07.0  0000:00:14.1  0000:00:1a.1  0000:00:1d.0  0000:00:1e.0  0000:01:00.1  0000:03:00.0  0000:06:03.0
0000:00:01.0  0000:00:09.0  0000:00:14.2  0000:00:1a.7  0000:00:1d.1  0000:00:1f.0  0000:02:00.0  0000:05:00.0
0000:00:03.0  0000:00:14.0  0000:00:1a.0  0000:00:1c.0  0000:00:1d.7  0000:01:00.0  0000:02:00.1  0000:05:00.1

这里显示的前面多了四个 0,cd 到对应的网卡里面:
jaseywang@ThinkPad:/sys/bus/pci/devices$ cd 0000\:05\:00.1
jaseywang@ThinkPad:/sys/bus/pci/devices/0000:05:00.1$ ls

broken_parity_status  config  driver  irq            local_cpus  msi_bus  numa_node  remove  resource   subsystem         subsystem_vendor  vendor
class                 device  enable  local_cpulist  modalias    net      power      rescan  resource0  subsystem_device  uevent            vpd
jaseywang@ThinkPad:/sys/bus/pci/devices/0000:05:00.1$ cat vendor
0x14e4
jaseywang@ThinkPad:/sys/bus/pci/devices/0000:05:00.1$ cat device
0x1639

上面这个就是 pci 的 vender ID 和 device ID 了,内核使用这些 ID 来准确的匹配设备对应的驱动,PCI 驱动会告诉内核,他们会支持哪些 vender/device ID,这样内核就知道该如何来匹配了。接下来到 pci_ids.h 这个定义了宏的文件里面找相关信息:
jaseywang@ThinkPad:~/linux/linux-2.6.32.28$ grep -i 0x14e4 include/linux/pci_ids.h
#define PCI_VENDOR_ID_BROADCOM          0x14e4
jaseywang@ThinkPad:~/linux/linux-2.6.32.28$ grep -i 0x1639 include/linux/pci_ids.h
#define PCI_DEVICE_ID_NX2_5709          0x1639
jaseywang@ThinkPad:~/linux/linux-2.6.32.28$ grep -Rl PCI_VENDOR_ID_BROADCOM *
arch/mips/pci/ops-bcm63xx.c
drivers/pci/quirks.c
drivers/net/b44.c
drivers/net/tg3.c
drivers/net/wireless/b43legacy/b43legacy.h
drivers/net/wireless/b43/phy_n.c
drivers/net/bnx2.c
drivers/pcmcia/bcm63xx_pcmcia.c
drivers/ssb/scan.c
drivers/ssb/b43_pci_bridge.c
include/linux/pci_ids.h
很明显的发现有一个 bxn2.c 驱动,进去搜索 PCI_VENDOR_ID_BROADCOM,发现一结构体中同时有 PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709 的存在,这个就是支持我们设备的驱动了:
    static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
      PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
      PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708 },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
      PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 },
    { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709S,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S },
    { PCI_VENDOR_ID_BROADCOM, 0x163b,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716 },
    { PCI_VENDOR_ID_BROADCOM, 0x163c,
      PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716S },
    { 0, }
};

总结一下获取 PCI 驱动的步骤:
1.通过 lspci 获取设备的 bus ID
2.cd 到 /sys/bus/pci/devices/0000:bus_id/ 目录
3.从该目录的 vendor 以及 device 文件读取对应的内容
4.到内核源码的 include/linux/pci_ids.h 文件中搜索包含前面 vendor 以及 device ID 的宏
5.搜索整个内核源码树,找到引用这些宏的文件,确认 vendor/device ID 必须在同一个 struct pci_device_id 定义中
6.搜索源码树的 Makefile 文件,找到以 CONFIG_ 开头的指令:
$ find -type f -name Makefile | xargs grep DRIVER_NAME
7.到内核的配置系统里买你搜索上面找出的关键字,选中编译

USB 设备跟 PCI 设备类似,有些细小的差别:
[jaseywang@TP ~]$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 008 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 009: ID 12d1:14ac Huawei Technologies Co., Ltd.

最佳的确认办法是现插到机器上,然后再拔出,再插入,就可以确实那个设备了。需要注意的是,插拔过程中,device number 会变,但是 vendor/device ID 不会变:
[jaseywang@TP ~]$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 008 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 010: ID 12d1:1446 Huawei Technologies Co., Ltd. E1552/E1800 (HSPA modem)

对于 huawei 的这台 USB 设备来说,vendor ID 为 12d1,device ID 为 1446。从 pci_ids.s 中没有找到对应的宏变量,直接在 drivers 源码中找:
[jaseywang@TP linux-2.6.32.59]$ grep -Ri -l  12d1 drivers/*
drivers/staging/otus/hal/hpfwu_txstream.c
drivers/staging/otus/hal/hpDKfwu.c
drivers/staging/otus/hal/hpfwu.c
drivers/staging/otus/hal/hpfwu_2k.c
drivers/staging/otus/hal/hpfwu_BA.c
drivers/staging/otus/hal/hpfw2.c
drivers/staging/otus/hal/hpfwu_FB50_mdk.c
drivers/staging/otus/hal/hpfwu.c.drv_ba_resend
drivers/staging/otus/hal/hpfwu_OTUS_RC.c
drivers/staging/otus/hal/hpfwbu.c
drivers/usb/storage/unusual_devs.h
drivers/usb/serial/option.c

发现 option.c 这个驱动的概率更大,进去确认:
#define HUAWEI_VENDOR_ID            0x12D1

static struct usb_device_id option_ids[] = {
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
    { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },

    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },

    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
    { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },

可以发现源码里面的 device 使用的是 16 进制表示的:HUAWEI_PRODUCT_E142E。可以确认 options.c 这个驱动就是我们要找的了。接下来要做的就是去 Makefile 里面,去内核配置里面找相应的模块了。

总结一下搜索 USB 驱动的步骤:
1.通过 lsusb 确认设备的 vendor/device ID
2.通过 vendor/device ID 关键词搜索,确保两个 ID 在通过一个 struct usb_device_id 结构体中
3.搜索 Makefile
$ find -type f -name Makefile | xargs grep DRIVER_NSME
4.进入内核配置,搜索,选中该驱动

一般情况下,我们使用的发行版本会有 ramdisk 这个文件。如果在启动的时候不使用该文件,需要将 root 分区以及该分区所在的物理盘的驱动编译进内核,而不是以模块的方式存在。如果在启动的时候使用 ramdisk,可以将上面这些编译成模块加载。一般情况下,如果使用的是发行版本,都会有 ramdisk。

接下来将会解释如何让 kernel 在启动的时候找到 root filesystem:
jaseywang@ThinkPad:~$ mount | grep " / "
/dev/sda5 on / type ext4 (rw,noatime,errors=remount-ro)

ext4 就是 / 使用的文件系统类型

去 sysfs 找到控制 /dev/sda5 的驱动,/sys/block/, /sys/class/block/ 最终都指向同一个链接:
jaseywang@ThinkPad:~$ tree -d /sys/block/ | egrep 'sd|hd'
└── sda -> ../devices/pci0000:00/0000:00:1c.0/0000:03:00.0/host0/target0:2:0/0:2:0:0/block/sda
jaseywang@ThinkPad:/sys/block$ ls -l /sys/block/sda
lrwxrwxrwx 1 root root 0 2012-05-01 17:09 /sys/block/sda -> ../devices/pci0000:00/0000:00:1c.0/0000:03:00.0/host0/target0:2:0/0:2:0:0/block/sda
jaseywang@ThinkPad:/sys/block$ ls -l /sys/devices/pci0000\:00/0000\:00\:1c.0/0000\:03\:00.0/host0/target0\:2\:0/0\:2\:0\:0/
total 0
drwxr-xr-x 3 root root    0 2012-05-01 17:09 block
drwxr-xr-x 3 root root    0 2012-05-01 17:09 bsg
–w——- 1 root root 4096 2012-05-02 18:19 delete
-r–r–r– 1 root root 4096 2012-05-02 18:19 device_blocked
-rw-r–r– 1 root root 4096 2012-05-02 18:19 dh_state
lrwxrwxrwx 1 root root    0 2012-05-01 17:09 driver -> ../../../../../../../bus/scsi/drivers/sd
-r–r–r– 1 root root 4096 2012-05-02 18:19 evt_media_change
lrwxrwxrwx 1 root root    0 2012-05-02 18:19 generic -> scsi_generic/sg1
-r–r–r– 1 root root 4096 2012-05-02 18:19 iocounterbits
-r–r–r– 1 root root 4096 2012-05-02 18:19 iodone_cnt
-r–r–r– 1 root root 4096 2012-05-02 18:19 ioerr_cnt
-r–r–r– 1 root root 4096 2012-05-02 18:19 iorequest_cnt
-r–r–r– 1 root root 4096 2012-05-02 01:23 modalias
-r–r–r– 1 root root 4096 2012-05-02 18:19 model
drwxr-xr-x 2 root root    0 2012-05-02 01:23 power
-r–r–r– 1 root root 4096 2012-05-02 18:19 queue_depth
-r–r–r– 1 root root 4096 2012-05-02 18:19 queue_type
–w——- 1 root root 4096 2012-05-02 18:19 rescan
-r–r–r– 1 root root 4096 2012-05-02 18:19 rev
drwxr-xr-x 3 root root    0 2012-05-01 17:09 scsi_device
drwxr-xr-x 3 root root    0 2012-05-01 17:09 scsi_disk
drwxr-xr-x 3 root root    0 2012-05-01 17:09 scsi_generic
-r–r–r– 1 root root 4096 2012-05-02 18:19 scsi_level
-rw-r–r– 1 root root 4096 2012-05-02 18:19 state
lrwxrwxrwx 1 root root    0 2012-05-01 17:09 subsystem -> ../../../../../../../bus/scsi
-rw-r–r– 1 root root 4096 2012-05-02 18:19 timeout
-r–r–r– 1 root root 4096 2012-05-01 17:09 type
-rw-r–r– 1 root root 4096 2012-05-01 17:09 uevent
-r–r–r– 1 root root 4096 2012-05-01 17:09 vendor
jaseywang@ThinkPad:/sys/block$ ls -l /sys/devices/pci0000\:00/0000\:00\:1c.0/0000\:03\:00.0/host0/target0\:2\:0/0\:2\:0\:0/driver
lrwxrwxrwx 1 root root 0 2012-05-01 17:09 /sys/devices/pci0000:00/0000:00:1c.0/0000:03:00.0/host0/target0:2:0/0:2:0:0/driver -> ../../../../../../../bus/scsi/drivers/sd

发现一个 sd 的驱动,继续寻找,看看还有没有需要的驱动了:
jaseywang@ThinkPad:/sys/block$ ls -l /sys/devices/pci0000\:00/0000\:00\:1c.0/0000\:03\:00.0/host0/target0\:2\:0/
total 0
drwxr-xr-x 8 root root    0 2012-05-01 17:09 0:2:0:0
drwxr-xr-x 2 root root    0 2012-05-02 01:23 power
lrwxrwxrwx 1 root root    0 2012-05-01 17:09 subsystem -> ../../../../../../bus/scsi
-rw-r–r– 1 root root 4096 2012-05-01 17:09 uevent
jaseywang@ThinkPad:/sys/block$ ls -l /sys/devices/pci0000\:00/0000\:00\:1c.0/0000\:03\:00.0/host0/
total 0
drwxr-xr-x 2 root root    0 2012-05-02 01:23 power
drwxr-xr-x 3 root root    0 2012-05-01 17:09 scsi_host
lrwxrwxrwx 1 root root    0 2012-05-01 17:09 subsystem -> ../../../../../bus/scsi
drwxr-xr-x 4 root root    0 2012-05-01 17:09 target0:0:32
drwxr-xr-x 4 root root    0 2012-05-01 17:09 target0:2:0
-rw-r–r– 1 root root 4096 2012-05-01 17:09 uevent
jaseywang@ThinkPad:/sys/block$ ls -l /sys/devices/pci0000\:00/0000\:00\:1c.0/0000\:03\:00.0/
total 0
-rw-r–r– 1 root root   4096 2012-05-02 18:22 broken_parity_status
-r–r–r– 1 root root   4096 2012-05-01 17:09 class
-rw-r–r– 1 root root   4096 2012-05-02 01:48 config
-r–r–r– 1 root root   4096 2012-05-02 01:48 device
lrwxrwxrwx 1 root root      0 2012-05-02 18:22 driver -> ../../../../bus/pci/drivers/megaraid_sas
-rw——- 1 root root   4096 2012-05-02 18:22 enable
drwxr-xr-x 6 root root      0 2012-05-01 17:09 host0
-r–r–r– 1 root root   4096 2012-05-01 17:09 irq
-r–r–r– 1 root root   4096 2012-05-02 18:22 local_cpulist
-r–r–r– 1 root root   4096 2012-05-01 17:09 local_cpus
-r–r–r– 1 root root   4096 2012-05-02 01:23 modalias
-rw-r–r– 1 root root   4096 2012-05-02 18:22 msi_bus
-r–r–r– 1 root root   4096 2012-05-02 18:22 numa_node
-r–r–r– 1 root root   4096 2012-05-02 18:22 pools
drwxr-xr-x 2 root root      0 2012-05-02 01:23 power
–w–w—- 1 root root   4096 2012-05-02 18:22 remove
–w–w—- 1 root root   4096 2012-05-02 18:22 rescan
–w——- 1 root root   4096 2012-05-02 18:22 reset
-r–r–r– 1 root root   4096 2012-05-02 01:48 resource
-rw——- 1 root root    256 2012-05-02 18:22 resource0
-rw——- 1 root root  16384 2012-05-02 18:22 resource1
-rw——- 1 root root 262144 2012-05-02 18:22 resource3
-r——– 1 root root 262144 2012-05-02 18:22 rom
lrwxrwxrwx 1 root root      0 2012-05-01 17:09 subsystem -> ../../../../bus/pci
-r–r–r– 1 root root   4096 2012-05-02 18:22 subsystem_device
-r–r–r– 1 root root   4096 2012-05-02 18:22 subsystem_vendor
-rw-r–r– 1 root root   4096 2012-05-01 17:09 uevent
-r–r–r– 1 root root   4096 2012-05-02 01:48 vendor
-rw——- 1 root root  32768 2012-05-02 18:22 vpd
jaseywang@ThinkPad:/sys/block$ ls -l /sys/devices/pci0000\:00/0000\:00\:1c.0/0000\:03\:00.0/driver
lrwxrwxrwx 1 root root 0 2012-05-02 18:22 /sys/devices/pci0000:00/0000:00:1c.0/0000:03:00.0/driver -> ../../../../bus/pci/drivers/megaraid_sas

又找到个叫 megaraid_sas 的驱动,至此,控制 / 的驱动分别是 ext4, sd, megaraid_sas 这三个驱动。

  • http://qczx.us/ 清纯与时尚

    对搞内核的人总是充满敬意!