1. 程式人生 > >Linux內核(2) - 分析內核源碼如何入手(上)

Linux內核(2) - 分析內核源碼如何入手(上)

會有 xtra signal per ike 自己 conn skeleton network

透過現象看本質,獸獸們無非就是一些人體藝術展示。同樣往本質裏看過去,學習內核,就是學習內核的源代碼,任何內核有關的書籍都是基於內核,而又不高於內核的。

既然要學習內核源碼,就要經常對內核代碼進行分析,而內核代碼千千萬,還前仆後繼的不斷往裏加,這就讓大部分人都有種霧裏看花花不見的無助感。不過不要怕,孔老夫子早就留給我們了應對之策:敏於事而慎於言,就有道而正焉,可謂好學也已。這就是說,做事要踏實才是好學生好同誌,要遵循嚴謹的態度,去理解每一段代碼的實現,多問多想多記。如果抱著走馬觀花,得過且過的態度,結果極有可能就是一邊看一邊丟,沒有多大的收獲。

子曰:“君子食無求飽,居無求安,敏於事而慎於言,就有道而正焉,可謂好學也已。”

孔子說:“君子,吃食不要求飽足,居住不要求舒適,對工作勤勞敏捷,說話卻謹慎,到有道的人那裏去匡正自己,這樣,可以說是好學了。”

假設全國房價上漲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部分,是要做很多的事為咱們分憂的,所以多點也是可以理解的。

Linux內核(2) - 分析內核源碼如何入手(上)