Linux內核開發之--將驅動程序添加到內核

一 . 概述:

在 linux 內核中增加程序需要完成以下三項工作:

1. 將編寫的源代碼複製到 Linux 內核源代碼的相應目錄

2. 在目錄的 Kconfig 文件中增加新源代碼對應項目的編譯配置選項

3. 在目錄的 Makefile 文件中增加對新源代碼的編譯條目


二 . 實例

1. 先把驅動代碼 usbtmc( 文件夾 ) 賦值到 /usr/src/linux-headers-2.6.32-31-generic/drivers/char 下

首先你要清楚你的模塊應在內核源代碼樹中處於何處。

1> 設備驅動程序存放在內核源碼樹根目錄 drivers/ 的子目錄下,在其內部,設備驅動文件進一步按照類別,類型等有序地組織起來。

a. 字符設備存在於 drivers/char/ 目錄下

b. 塊設備存放在 drivers/block/ 目錄下

c.USB 設備則存放在 drivers/usb/ 目錄下。

注意:

(1) 此處的文件組織規則並非絕對不變,例如: USB 設備也屬於字符設備,也可以存放在 drivers/usb/ 目錄下。

(2) 例如我們把驅動程序 usbtmc 存放在 drivers/char/ 目錄下,那麼你要注意,在該目錄下同時會存在大量的 C 源代碼文件和許多其他目錄。所有對於僅僅只有一兩個源文件的設備驅動程序,可以直接存放在該目錄下,但如果驅動程序包含許多源文件和其他輔助文件,那麼可以創建一個新子目錄。

此處,我們是把 usbtmc 目錄放在了 drivers/char 目錄下面

2. 修改 char 目錄下的 Kconfig 和 Makefile

(1) 修改 Kconfig

sudo gedit Kconfig

添加下面一句後

source "drivers/char/usbtmc/Kconfig"

它表示將 usbtmc 目錄下的 Kconfig 掛載到 char 目錄下的 Kconfig 裏面 ( 爲了使本層的 Kconfig 文件能起作用,我們需要修改父目錄的 Kconfig 文件,加入 source 語句 )

1> 對驅動程序而言, Kconfig 通常和源代碼處於同一目錄。

2> 如果你建立了一個新字目錄,而且也希望 Kconfig 文件存在於該目錄中的話,那麼就必須在一個已存在的 Kconfig 文件中將它引入,需要用上面的

語句將其掛接在 drivers/char 目錄中的 Kconfig 中。

(2) 修改 Makefile

添加一句話:

obj-$(CONFIG_USBTMC) +=usbtmc/

這行編譯指令告訴模塊構建系統在編譯模塊時需要進入 usbtmc/ 子目錄中。此時的驅動程序的編譯取決於一個特殊配置 CONFIG_USBTMC 配置選項。

3. 現在在我們自己些驅動程序文件夾中添加 Kconfig 和 Makefile

(1) 修改 Kconfig

新建一個 Kconfig 添加下面的話

menu "USBTMC"

comment "USBTMC Driver"

config USBTMC

tristate "USBTMC"

default n

help

If you say Y here,support for the usbtmc with computer interface will be compiled into he kernel and accessible via device node. You can also say M here and the driver will be built as a module named usbtmc.ko.

If unsure,say N.

endmenu

endmenu

正確配置好後,我們在源碼下執行 sudo make menuconfig 後,在出現的 Linux Kernel Configuration 圖形界面中選擇 Device Drivers 下的 character devcie 中 ,將會看到新加的 USBTCM 菜單,

(2) 修改 Makefile

新建一個 Makefile ,添加下面的話

obj-$(CONFIG_USBTMC) +=usbtmc.o

此時,構建系統運行就將會進入 usbtmc/ 目錄下,並且將 usbtmc.c 編譯爲 usbtmc.ko 模塊

注:

如果驅動程序源文件可能不只有一個,可以把 Makefile 做如下修改:

obj-$(CONFIG_USBTMC) +=usbtmc.o

usbtmc-objs :=usbtmc-main.o usbtmc-usb1.o

此時, usbtmc-main.c 和 usbtmc-usb1.c 就一起被編譯和連接到了 usbtmc.ko 某塊中。

4. 現在已經 Ok 了,現在我們可以進入 linux 內核目錄下通過 menuconfig 可以找到我們的 USBTMC 選項(在 Device_Drivers 下的 character devices 裏可以找到 USBTMC )對其進行選定。然後退出,編譯內核,就搞定了。

5. 刪除:

刪除也很簡單,首先在 drivers/char 目錄下刪掉自己的驅動文件夾。其次再刪除 Makefile 和 Kconfig 之前添加的東西,就搞定了

三 . 詳解:

Makefile , Kconfig 和配置工具組成了 Linux 2.6 內核的配置系統。 
其中 Makefile 定義了 Linux 內核的編譯規則,它是大型項目開發的產物。 Linux 環境下的大型項目開發中,系統被分爲很多模塊,而這些模塊一般會經歷幾次修改,而在修改後的編譯過程中,由於某些文件中存在依賴關係,人工編譯效率低 ( 有些文件不需要重新編譯 ) 且易出錯, Makefile 文件便應運而生。 Makefile 文件定義了模塊間的依賴關係,指定文件的編譯順序,以及編譯所使用的命令。它和 make 命令使得項目的源程序文件可以自動編譯,提高了軟件開發效率。到此,再談一下 make ,它是用來維護程序模塊關係和生成可執行程序的工具,它可以根據程序模塊的修改情況重新編譯鏈接生成中間代碼或最終的可執行程序,省去那些重複的不必要的編譯工作,提高編譯效率。 
Kconfig 給用戶提供配置選擇的功能。通常配置內核會有四種方法, make config (字符界面配置), make menuconfig (菜單界面配置), make xconfig (依賴 QT ), make gconfig (依賴 GTK+ )。 make config 比較適合專業人員,像初學者比較適合 make menuconfig ,讓我們重點關注一下它。當我們運行 make menuconfig 時,配置工具會首先分析與體系結構相對應的 /arch/xxx/Kconfig 文件( xxx 爲傳入的 arch 參數),它裏面包含了除一些與體系結構相關的配置項和配置菜單外,還通過 source 語句引入了一系列 Kconfig ,配置工具依據這些 Kconfig 包含的菜單和項目就可以描繪出一個分層結構。 
例如當我們運行 make zImagine 、 make bzImagine 等生成映像的命令時,會先檢索頂層的 Makefie (在 arch/xxx/ 目錄下的 Makefile 爲頂層 Makefile 補充體系結構相關的信息),頂層 Makefile 的兩個主要任務是:產生內核映像文件和內核模塊。接着頂層 Makefile 會去遞歸地進入內核的各個子目錄,然後分別調用子目錄中的 Makefile (這些 Makefile 記錄編譯目標),而進入哪些子目錄取決於內核的配置。 
當使用 make menuconfig , make config 命令時,生成的 .config 會在源碼目錄下記錄哪些部分被編譯入內核,哪些部分被編譯爲內核模塊。簡而言之,它是保存內核配置結果的文件。當我們裝上 Linux 系統時,第一次查看源碼下的所有文件,會發現沒有 .config 文件,那是因爲從來沒配置過內核。當你運行 make menuconfig 保存並退出時,再次查看就有這個文件了。 
配置工具,包括配置命令解釋器(對配置腳本中使用的命令進行解釋)和配置用戶界面(提供字符界面和圖形界面),配置工具都是用腳本語言編寫的。

 

1. 在進入 menuconfig 配置界面時,會發現每個配置項目爲布爾型(要麼編譯入內核,要麼不編譯,選項爲“ Y” 或“ N” ),菜單上爲配置選項的名字例如:“ XXX Driver”,help 後面的內容爲幫助信息。

1> 除了布爾型的配置項目外,還存在一種三態型 (tristate) 配置選項,它意味着要麼編譯入內核,要麼編譯爲內核模塊,要麼不編譯,選項爲“ Y” ,“ M” 或“ N” 。

eg: obj-$(CONFIG_USBTMC) +=usbtmc.o

上面的腳本含義是:如果 USBTMC 選項被選擇爲“ Y” 或“ M” ,即 obj-$(CONFIG_USBTMC) 就等同於 obj-y 或 obj-m 時,則編譯 usbtmc.c ,選 Y 的情況直接會將生成的目標代碼直接連接到內核,爲“ M” 的情況則會生成模塊 usbtmc.ko ,如果 USBTMC 配置選項被選擇爲“ N” ,即 obj-$(CONFIG_USBTMC) 等同於 obj-n 時,則不編譯 usbtmc.c

2.Makefile

對內核源代碼各級子目錄中的 kbuild Makefile 進行介紹,

(1) 目標定義

目標定義用來定義哪些內容要作爲模塊編譯,哪些要編譯並連接進內核

(a)obj-y:=foo.o

表示要由 foo.c 或者 foo.s 文件編譯得到 foo.o 並連接進內核,而 obj-m 則表示該文件要作爲模塊編譯。處了 y,m 以外的 obj-x 形式的目標都不會被編譯。

( b) 我們最常用的的做法是根據 .config 文件的 CONFIG_ 變量來決定文件的編譯方式:

eg:

obj-$(CONFIG_ISDN) +=isdn.o

(c) 多個文件模塊的定義

如果一個模塊由多個文件組成,這時候應採用模塊名加 -objs 後綴或者 -y 後綴的形式來定義模塊的組成文件。

如:

obj-$(CONFIG_EXT2_FS) +=ext2.o

ext2-y :=balloc.o bitmap.o

模塊的名字是 ext2, 由 balloc.o 和 bitmap.o 兩個文件最終連接生成 ext2.o 直至 ext2.ko 文件。

3.Kconfig

內核配置腳本語法:

(1) 大多數的內核配置選項都對應一個 Kconfig 中的一個菜單入口。

menu "USBTMC"

comment "USBTMC Driver"

config USBTMC

tristate "USBTMC"

default n

endmenu

(a)“config” 關鍵字定義新的配置選項,之後的幾行定義了該配置選項的屬性。配置選項的屬性包括類型,數據 , 輸入提示,依賴關係(及反向依賴關係),幫助信息和默認值等。

(b) 每個配置選項都必須指定類型,其他類型都基於這兩種基本類型。類型定義後可以緊跟輸入提示,下面兩個腳本是等價的

腳本 1 :

bool “Networking support”

腳本 2 :

bool

promt “Networking support”

輸入提示的一般格式如下提示:

prompt <prompt> [if <expr>]

其中可選的 if 用來表示該提示的依賴關係。

默認值的格式如下所示:

default <expr> [if <expr>]

一個配置選項可以存在任意多個默認值,這種情況下,只有第一個被定義的值是可用的。如果用戶不設置對應的選項,配置選項的值就是默認值。

(c) 依賴關係的格式如下所示:

depends on ( 或者 requires) <expr>

如果定義了多個依賴關係,它們之間用” &&” 間隔。依賴關係也可以應用到該菜單中所有的其他選項中。

(4) 反向依賴關係的格式如下所示:

select <symbol> [if <expr>]

A.depends 能限定一個 symbol 的上限,即如果 A 依賴於 B ,則在 B 被配置爲“ Y” 的情況下, A 可以爲“ Y” ,“ M” 和” N”; 在 B 被配置爲“ M” 的情況下, A 可以被配置爲“ M” 或“ N” ; B 在被配置爲“ N” 的情況下, A 只能爲” N” 。

B.select 能限定一個 symbol 的下限,若 A 反向依賴於 B ,則 A 的配置值會高於或等於 B (正好與 depends 相反)。如果 symbol 反向依賴於多個對象,則它的下限是這些對象的對大值。

(5) 幫助信息的格式如下:

help( 或 ---help---)

開始

。。。

結束

幫組信息完全靠文本縮進識別結束。“ ---help---” 和” help” 的初衷在於將文件中的配置邏輯與給開發人員的提示分開。

3. 菜單結構

菜單入口在菜單數結構中的位置可由兩種方法決定。

(1) 第一中方式如下所下:

menu “Network device support”

depends on NET

config NETDEVICES


endmenu

所有處於” menu” 和” endmenu” 之間的菜單入口都會成爲“ Network device support” 的子菜單。而且,所有子菜單選項都會繼承父菜單的依賴關係,比如:“ Network device support” 對“ NET” 的依賴被加到了配置選項 NETDEVICES 的依賴列表中。

(2) 另一種方式是通過分析依賴關係生成菜單結構。如果菜單選項在一定程度上依賴於前面的選項,它就能成爲該選項的子菜單。如果父選項爲“ N” ,則子選項不可見;如果父選項爲“ Y” 或“ M” ,則子選項可見。

Eg:

config MODULES

bool “Enable loadable module support”

config MODVERSIONS

bool “Set version information on all module symbole”

depends on MODULES

 

comment “module support disabled”

 

depends on !MODULES

 

MODVERSIONS 直接依賴 MODULES ,如果 MODULES 不爲“ N” ,該選項纔可見。

(3) 除此之外, Kconfig 中還可能使用“ choices …...endchoice”,”comment”,”if....endif” 這樣的語法結構。

其中

choice

<choice options>

<choice block>

enchoice

它定義一個選擇羣,其接受的選項( choice options )可以是前面描述的任何屬性。在一個硬件有多個驅動的情況下使用,使用選擇可以實現最終只有一個驅動被編譯進內核或模塊。選擇羣還可以接受的另一個選項是“ optional”,

這樣菜單入口就被設置爲“ N” ,沒有被選中。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章