《Linux內核修煉之道》精華分享與討論(6)——分析內核源碼如何入手?(上)

透過現象看本質,獸獸門無非就是一些人體藝術展示。同樣往本質裏看過去,學習內核,就是學習內核的源代碼,任何內核有關的書籍都是基於內核,而又不高於內核的。
既然要學習內核源碼,就要經常對內核代碼進行分析,而內核代碼千千萬,還前仆後繼的不斷往裏加,這就讓大部分人都有種霧裏看花花不見的無助感。不過不要怕,孔老夫子早就留給我們了應對之策:敏於事而慎於言,就有道而正焉,可謂好學也已。這就是說,做事要踏實才是好學生好同志,要遵循嚴謹的態度,去理解每一段代碼的實現,多問多想多記。如果抱着走馬觀花,得過且過的態度,結果極有可能就是一邊看一邊丟,沒有多大的收穫。
假設全國房價上漲1.5%,假設80後局長是農民子弟,⋯⋯,既然我們的人生充滿了假設,那麼我在這裏假設你現在就迫不及待的希望研究內核中USB子系統的實現,應該沒有意見吧?那好,下面就以USB子系統的實現分析爲標本看看分析內核源碼應該如何入手。

分析README
內核中USB子系統的代碼位於目錄drivers/usb,這個結論並不需要假設。於是我們進入到該目錄,執行命令ls,結果顯示如下:
atm  class  core  gadget  host  image  misc  mon  serial  storage Kconfig 
Makefile  README usb-skeleton.c

目錄drivers/usb共包含有10個子目錄和4個文件,usb-skeleton.c是一個簡單的USB driver的框架,感興趣的可以去看看,目前來說,它還吸引不了我們的眼球。那麼首先應該關注什麼?如果迎面走來一個ppmm,你會首先看臉、腳還是其它?當然答案依據每個人的癖好會有所不同。不過這裏的問題應該只有一個答案,那就是Kconfig、Makefile、README。
README裏有關於這個目錄下內容的一般性描述,它不是關鍵,只是幫助你瞭解。再說了,面對“read我吧read我吧”這麼熱情奔放的呼喚,善良的我們是不可能無動於衷的,所以先來看看裏面都有些什麼內容。
23 Here is a list of what each subdirectory here is, and what is contained in
24 them.
25
26 core/        - This is for the core USB host code, including the
27             usbfs files and the hub class driver ("khubd").
28
29 host/        - This is for USB host controller drivers.  This
30             includes UHCI, OHCI, EHCI, and others that might
31             be used with more specialized "embedded" systems.
32
33 gadget/        - This is for USB peripheral controller drivers and
34             the various gadget drivers which talk to them.
35
36
37 Individual USB driver directories.  A new driver should be added to the
38 first subdirectory in the list below that it fits into.
39
40 image/        - This is for still image drivers, like scanners or
41             digital cameras.
42 input/        - This is for any driver that uses the input subsystem,
43             like keyboard, mice, touchscreens, tablets, etc.
44 media/        - This is for multimedia drivers, like video cameras,
45             radios, and any other drivers that talk to the v4l
46             subsystem.
47 net/        - This is for network drivers.
48 serial/        - This is for USB to serial drivers.
49 storage/    - This is for USB mass-storage drivers.
50 class/        - This is for all USB device drivers that do not fit
51             into any of the above categories, and work for a range
52             of USB Class specified devices.
53 misc/        - This is for all USB device drivers that do not fit
54             into any of the above categories.

這個README文件描述了前邊使用ls命令列出的那10個文件夾的用途。那麼什麼是USB Core?Linux內核開發者們,專門寫了一些代碼,負責實現一些核心的功能,爲別的設備驅動程序提供服務,比如申請內存,比如實現一些所有的設備都會需要的公共的函數,並美其名曰USB Core。
時代總在發展,當年胖楊貴妃照樣迷死唐明皇,而如今人們欣賞的則是林志玲這樣的魔鬼身材。同樣,早期的Linux內核,其結構並不是如今天這般有層次感,遠不像今天這般錯落有致,那時候drivers/usb/這個目錄下邊放了很多很多文件,USB Core與其他各種設備的驅動程序的代碼都堆砌在這裏,後來,怎奈世間萬千的變幻,總愛把有情的人分兩端。於是在drivers/usb/目錄下面出來了一個core目錄,就專門放一些核心的代碼,比如初始化整個USB系統,初始化Root Hub,初始化主機控制器的代碼,再後來甚至把主機控制器相關的代碼也單獨建了一個目錄,叫host目錄,這是因爲USB主機控制器隨着時代的發展,也開始有了好幾種,不再像剛開始那樣只有一種,所以呢,設計者們把一些主機控制器公共的代碼仍然留在core目錄下,而一些各主機控制器單獨的代碼則移到host目錄下面讓負責各種主機控制器的人去維護。
那麼USB gadget那?gadget白了說就是配件的意思,主要就是一些內部運行Linux的嵌入式設備,比如PDA,設備本身有USB設備控制器(USB Device Controller),可以將PC,也就是我們的主機作爲master端,將這樣的設備作爲slave端和主機通過USB進行通信。從主機的觀點來看,主機系統的USB驅動程序控制插入其中的USB設備,而USB gadget的驅動程序控制外圍設備如何作爲一個USB設備和主機通信。比如,我們的嵌入式板子上支持SD卡,如果我們希望在將板子通過USB連接到PC之後,這個SD卡被模擬成U盤,那麼就要通過USB gadget架構的驅動。
剩下的幾個目錄分門別類的放了各種USB設備的驅動,比如U盤的驅動在storage目錄下,觸摸屏和USB鍵盤鼠標的驅動在input目錄下,等等。
我們響應了README的熱情呼喚,它便給予了我們想要的,通過它我們瞭解了USB目錄裏的那些文件夾都有着什麼樣的角色。到現在爲止,就只剩下內核的地圖——Kconfig與Makefile兩個文件了。有地圖在手,對於在內核中游蕩的我們來說,是件很愉悅的事情,不過,因爲我們的目的是研究內核對USB子系統的實現,而不是特定設備或host controller的驅動,所以這裏的定位很明顯,USB Core就是我們需要關注的對象,那麼接下來就是要對core目錄中的內容進行定位了。

分析Kconfig和Makefile

進入到drivers/usb/core目錄,執行命令ls,結果顯示如下:
Kconfig  Makefile  buffer.c  config.c  devices.c  devio.c  driver.c 
endpoint.c  file.c  generic.c  hcd-pci.c  hcd.c  hcd.h  hub.c  hub.h 
inode.c  message.c  notify.c  otg_whitelist.h  quirks.c  sysfs.c  urb.c 
usb.c  usb.h

然後執行wc命令,如下所示。
# wc –l ./*
   148 buffer.c
   607 config.c
   706 devices.c
  1677 devio.c
  1569 driver.c
   357 endpoint.c
   248 file.c
   238 generic.c
  1759 hcd.c
   458 hcd.h
   433 hcd-pci.c
  3046 hub.c
   195 hub.h
   758 inode.c
   144 Kconfig
    21 Makefile
  1732 message.c
    68 notify.c
   112 otg_whitelist.h
   161 quirks.c
   710 sysfs.c
   589 urb.c
   984 usb.c
   160 usb.h
 16880 total

drivers/usb/core目錄共包括24個文件,16880行代碼。core不愧是core,爲大家默默的做這麼多事。不過這麼多文件裏不一定都是我們所需要關注的,先拿咱們的地圖來看看接下來該怎麼走。先看看Kconfig文件,可以看到下面的選項。
15 config USB_DEVICEFS
16         bool "USB device filesystem"
17         depends on USB
18         ---help---
19           If you say Y here (and to "/proc file system support" in the "File
20           systems" section, above), you will get a file /proc/bus/usb/devices
21           which lists the devices currently connected to your USB bus or
22           busses, and for every connected device a file named
23           "/proc/bus/usb/xxx/yyy", where xxx is the bus number and yyy the
24           device number; the latter files can be used by user space programs
25           to talk directly to the device. These files are "virtual", meaning
26           they are generated on the fly and not stored on the hard drive.
27
28           You may need to mount the usbfs file system to see the files, use
29           mount -t usbfs none /proc/bus/usb
30
31           For the format of the various /proc/bus/usb/ files, please read
32           <file:Documentation/usb/proc_usb_info.txt>.
33
34           Usbfs files can't handle Access Control Lists (ACL), which are the
35           default way to grant access to USB devices for untrusted users of a
36           desktop system. The usbfs functionality is replaced by real
37           device-nodes managed by udev. These nodes live in /dev/bus/usb and
38           are used by libusb.

選項USB_DEVICEFS與usbfs文件系統有關。usbfs文件系統掛載在/proc/bus/usb目錄,顯示了當前連接的所有USB設備及總線的各種信息,每個連接的USB設備在其中都會有一個對應的文件進行描述。比如文件/proc/bus/usb/xxx/yyy,xxx表示總線的序號,yyy表示設備所在總線的地址。不過不能夠依賴它們來穩定地訪問設備,因爲同一設備兩次連接對應的描述文件可能會不同,比如,第一次連接一個設備時,它可能是002/027,一段時間後再次連接,它可能就已經改變爲002/048。
就好比好不容易你暗戀的mm今天見你的時候對你拋了個媚眼,你心花怒放,趕快去買了100塊彩票慶祝,到第二天再見到她的時候,她對你說你是誰啊,你悲痛欲絕的刮開那100塊彩票,上面清一色的謝謝你。
因爲usbfs文件系統並不屬於USB子系統實現的核心部分,與之相關的代碼我們可以不必關注。
74 config USB_SUSPEND
75       bool "USB selective suspend/resume and wakeup (EXPERIMENTAL)"
76       depends on USB && PM && EXPERIMENTAL
77       help
78         If you say Y here, you can use driver calls or the sysfs
79         "power/state" file to suspend or resume individual USB
80         peripherals.
81
82         Also, USB "remote wakeup" signaling is supported, whereby some
83         USB devices (like keyboards and network adapters) can wake up
84         their parent hub.  That wakeup cascades up the USB tree, and
85         could wake the system from states like suspend-to-RAM.
86
87         If you are unsure about this, say N here.

這一項是有關USB設備的掛起和恢復。開發USB的人都是節電節能的好孩子,所以協議裏就規定了,所有的設備都必須支持掛起狀態,就是說爲了達到節電的目的,當設備在指定的時間內,如果沒有發生總線傳輸,就要進入掛起狀態。當它收到一個non-idle的信號時,就會被喚醒。節約用電從USB做起。不過這個與主題也沒太大關係,相關代碼也可以不用關注了。
剩下的還有幾項,不過似乎與咱們關係也不大,還是去看看Makefile。
5 usbcore-objs    := usb.o hub.o hcd.o urb.o message.o driver.o \
6                         config.o file.o buffer.o sysfs.o endpoint.o \
7                         devio.o notify.o generic.o quirks.o
8
9 ifeq ($(CONFIG_PCI),y)
10         usbcore-objs    += hcd-pci.o
11 endif
12
13 ifeq ($(CONFIG_USB_DEVICEFS),y)
14         usbcore-objs    += inode.o devices.o
15 endif
16
17 obj-$(CONFIG_USB)       += usbcore.o
18
19 ifeq ($(CONFIG_USB_DEBUG),y)
20 EXTRA_CFLAGS += -DDEBUG
21 endif

Makefile可比Kconfig簡略多了,所以看起來也更親切點,咱們總是拿的money越多越好,看的代碼越少越好。這裏之所以會出現CONFIG_PCI,是因爲通常USB的Root Hub包含在一個PCI設備中。hcd-pci和hcd顧名而思義就知道是說主機控制器的,它們實現了主機控制器公共部分,按協議裏的說法它們就是HCDI(HCD的公共接口),host目錄下則實現了各種不同的主機控制器。
CONFIG_USB_DEVICEFS前面的Kconfig文件裏也見到了,關於usbfs的,與咱們的主題無關,inode.c和devices.c兩個文件也可以不用管了。
那麼我們可以得出結論,爲了理解內核對USB子系統的實現,我們需要研究buffer.c、config.c、driver.c、endpoint.c、file.c、generic.c、hcd.c  hcd.h、hub.c、message.c、notify.c、otg_whitelist.h、quirks.c、sysfs.c、urb.c 和usb.c文件。這麼看來,好像大都需要關注的樣子,沒有減輕多少壓力,不過這裏本身就是USB Core部分,是要做很多的事爲咱們分憂的,所以多點也是可以理解的。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章