天天看點

《Linux核心修煉之道》——分析核心源碼如何入手?(上) 《Linux核心修煉之道》——分析核心源碼如何入手?(上)

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

  假設全國房價上漲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

  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.

  時代總在發展,當年胖楊貴妃照樣迷死唐明皇,而如今人們欣賞的則是林志玲這樣的魔鬼身材。同樣,早期的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部分,是要做很多的事為咱們分憂的,是以多點也是可以了解的

本文出自seven的測試人生公衆号最新内容請見作者的github頁:http://qaseven.github.io/

繼續閱讀