linux驱动内核哪个文件夹,linux设备驱动归纳总结(一):内核的相关基础概念...
linux設備驅動歸納總結(一):內核的相關基礎概念
1. 內核與 linux 設備驅動的作用與關系
內核:用于管理軟硬件資源,并提供運行環境。如分配 4G 虛擬空間等。
linux 設備驅動:是連接硬件和內核之間的橋梁。
linux 系統按個人理解可按下劃分:
1). 應用層:包括 POSIX 接口, LIBC ,圖形庫等,用于給用戶提供訪問內核的接口。屬于用戶態 ARM 運行在用戶模式 (usr) 或者系統模式 (sys) 下。
2). 內核層:應用程序調用相關接口后,會通過系統調用,執行 SWI 指令切換 ARM 的工作模式到超級用戶(svc) 模式下,根據用戶函數的要求執行相應的操作。
3). 硬件層:硬件設備,當用戶需要操作硬件時,內核會根據驅動接口操作硬件設備
圖結構如下:
舉一個相對比較邪惡的類比:
在深圳的酒店經常會在門縫看到一些卡片,上面說可以通過打電話送貨上門提供某中服務。
===============================================
2. 內核代碼樹介紹
linux-2.6.29
|- arch :包含和硬件體系結構相關的代碼
|- block:硬盤調度算法,不是驅動
|- firmware:固件
|- Documentation:標準官方文檔
|- dirver: linux 設備驅動
|- fs:內核所支持的文件體系
|- include:頭文件。 linux/module.h linux/init.h常用庫。
|- init:庫文件代碼, C 庫函數在內核中的實現。
init/main.c ->start_kernel-> 內核執行第一條代碼
|- ipc :進程件通信
|- mm:內存管理
|- kernel:內核核心部分,包括進程調度等
|- net:網絡協議
|- sound:所有音頻相關
其中,跟設備驅動有關并且經常查閱的文件夾有:
init
include : linux, asm-arm
drivers:
arch:
===============================================
3. 內核補丁:
補丁一般都是基于某個版本內核生成的,用于升級舊內核。
打補丁需要注意:
1. 對應版本的補丁只能用于對應版本的內核。
2. 如果在已打補丁的內核再打補丁,需要先卸載原來補丁。
打補丁的方法:
1. 制作補丁:
diff -Nur linux-2.6.30/ linux-2.6.30.1/ > linux-2.6.30.1.patch
//N 為新加的文件全部修改
//linux-2.6.30舊版本
//linux-2.6.30.1新版本
// 目標補丁
2. 打補丁:
cd linux-2.6.30// !!注意在原文件夾的目錄中打補丁
patch -p1 < ../linux-2.6.30.1.patch//-p1 是忽略一級目錄
3. 恢復:
cd linux-2.6.30// !!注意在原文件夾的目錄中打補丁
patch -R < ../linux-2.6.30.1.patch// 撤銷補丁
===============================================
4. 內核中的 Makefile :
對于內核, Makefile 分為 5 類:
Documentation/kbuild/makefiles.txt 描述如下:
50 The Makefiles have five parts:
51
52Makefile總Makefile,控制內核的編譯
53.config內核配置文件,配置內核時生成,如make menuconfig后
54arch/$(ARCH)/Makefile對應體系結構的Makefile
55scripts/Makefile.*Makefile共用的規則,如圖形配置界面。
56kbuild Makefiles各子目錄下的Makefile,被上層的Makefile調用
簡單來說,編譯內核會執行以下事情。
1.make menuconfig
1.1 拷貝一個對應體系結構的配置文件到主目錄下并改名為 .config ,這樣就在 makemenuconfig生成的圖形配置中已經有了一些默認的配置,減少用戶的勞動量。
1.2 從內核頂層目錄的 Makefile 決定編譯的體系結構 (ARCH). 編譯工具 (CROSS_COMPILE) 和需要進去編譯的目錄。
1.3 根據總 Makefile 的 ARCH 變量,進入相應體系結構的目錄,讀取 arch/$(ARCH)/Makefile, 決定對應的體系結構下還有哪些目錄需要編譯。
1.4 根據 arch/$(ARCH)/Makefile ,一個一個地遞歸進入指定的目錄下調用該目錄下的 makefile ,并根據目錄下的 Kconfig 生成配置界面并由用戶決定將該文件編譯成模塊還是編譯進內核。
1.5 配置完畢后保存退出,會更改原來的 .config 的內容。
2.make
1.1 將生成的 .config 去掉注釋,新建一份配置文件,文件名為 include/config/auto.conf 。
1.2 根據配置文件的要求,將需要編譯的文件的各個子目錄下生成一個 .o 或者 .a 文件,然后由總Makefile 指定的連接腳本 arch/$(ARCH)/kernel/vmlinux.lds 生成 vmlinux ,并通過壓縮變成bzImage ,或者按要求在對應的子目錄下編譯成模塊。
但是,具體是怎么生成配置文件的呢?
注:我使用的內核是被修改過的,可能有些地方和原內核不一樣,如我內核里面 $(ARCH) 寫成$(SRCARCH) 。還有在文件中的行數和原內核不一致,但這些不影響分析,搜索一下就出來了。
1. 在總 Makefile 中,根據以下語句進入需要編譯的目錄
470 # Objects we will link into vmlinux / subdirs we need to visit
471 init-y:= init/
472 drivers-y:= drivers/ sound/ firmware/
473 net-y:= net/
474 libs-y:= lib/
475 core-y:= usr/
476 endif # KBUILD_EXTMOD
639 core-y+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
#另外還有一個體系相關的arch目錄
529 include $(srctree)/arch/$(SRCARCH)/Makefile
這樣,就根據了體系結構決定了需要進去編譯的目錄了。
2. 在總 Makefile 中包含的目錄還是不夠的,內核還需要根據對應的 CPU 體系架構,決定還需要將哪些子目錄將要編譯進內核,在總 Makefile 中進去讀取相應體系結構的 Makefile : arch/$(SRCARCH)/Makefile。
在總 Makefile 和體系架構下的 arch/(SRCARCH)/Makefile 中包含的子目錄會根據該目錄下的 Makefile的要求編譯成模塊還是編譯進內核,當然也可以不編譯。
如在arch/arm/Makefile下:
187 # If we have a machine-specific directory, then include it in the build.
188 core-y+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
189 core-y+= $(machdirs) $(platdirs)
190 core-$(CONFIG_FPE_NWFPE)+= arch/arm/nwfpe/
191 core-$(CONFIG_FPE_FASTFPE)+= $(FASTFPE_OBJ)
192 core-$(CONFIG_VFP)+= arch/arm/vfp/
193
194 drivers-$(CONFIG_OPROFILE)+= arch/arm/oprofile/
195
196 libs-y:= arch/arm/lib/ $(libs-y)
其中, y 表示編譯成模塊, m 表示編譯進內核 ( 上面沒有,因為默認情況下 ARM 全部編譯進內核 ) ,但$(CONFIG_OPROFILE) 又是什么呢?
這些是根據用戶在 make menuconfig 中設置后,生成的值賦給了 CONFIG_OPROFILE 。這是由各子目錄下的 Kconfig 提供選項功用戶選擇并配置。如 arch/arm/Kconfig 。
另外有些配置會根據 arch/$(ARCH)/Kconfig 文件通過 Kconfig 的語法 source 讀取各個包含的子目錄Kconfig 來生成一個配置界面。每個 Makefile 目錄下都有一個對應 Kconfig 文件,用于生成配置界面來給用戶決定內核如何配置。
總結 Kconfig 的作用:
2.1. 在 make menuconfig 下可以配置選項 ;
2.2. 在 .config 中確定 CONFIG_XXX 的的值。
3. 只是讀取以上的兩個 Makefile 還是不夠了,內核還會把包含的子目錄一層一層的讀取它里面的 Makefile和 Kconfig 。
假設我現在配置內核
1. 最簡單的方法,直接修改子目錄的 Makefile
如在我要取消 s3c2440 的時鐘 ( 當然這是必須要開的,只是舉例 ) 。
可以直接修改 arch/arm/mach-s3c2440/Makefile
12 obj-$(CONFIG_CPU_S3C2440)+= s3c2440.o dsc.o
13 obj-$(CONFIG_CPU_S3C2440)+= irq.o
14 obj-$(CONFIG_CPU_S3C2440)+= clock.o
15 obj-$(CONFIG_S3C2440_DMA)+= dma.o
將 obj-$(CONFIG_CPU_S3C2440)+= clock.o 改為
obj-+= clock.o
也可以編譯成模塊:
obj-m+= clock.o
2. 當然有更方便的通過圖形界面, make menuconfig ,接下來我實現一下如何將一個選項加入到圖形配置界面中。
2.1. 進入內核目錄
cd linux-2.6.29
2.2. 在 driver 目錄下模擬一個名為 test1 驅動的文件夾
mkdir driver/test1
2.3. 在 test1 目錄下隨便寫個 C 文件
cd driver/test1
vim test1.c
1 void foo()
2 {
3 ;
4 }
2.4. 在目錄下編寫一個簡單的 Makefile
vim Makefile
obj-$(CONFIG_TEST1) += test1.o
CONFIG_TEST1 是決定 test1 是否編譯進內核或者編譯成模塊的。這就通過 Kconfig 由用戶在make menuconfig 中選擇。
2.5. 所以還要在目錄下寫一個 Kconfig
vim Kconfig
1 menu "test1 driver here"
2 config TEST1
3bool "xiaobai test1 driver"
4help
5This is test1
6 endmenu
說白了,就是在圖形配置的 driver 下多了一個配置選項,用戶配置后將 CONFIG_TEST1 的值存放在.config 中, Makefile 通過讀取 .config 的去注釋版 autoconf 讀取到 CONFIG_TEST 的值,再進行編譯。但是,以上幾步還不能達到目的,因為雖然在總 Makefile 中已經包含了目錄 driver, 但是 driver 目錄的 Makefile 中并沒有包含 test 目錄。因此需要在 driver/Makefile 中添加:
2.6.vim driver/Makefile
再最后加上一句:
104 obj-$(CONFIG_OF)+= of/
105 obj-$(CONFIG_SSB)+= ssb/
106 obj-$(CONFIG_VIRTIO) += virtio/
107 obj-$(CONFIG_STAGING)+= staging/
108 obj-y+= platform/
109 obj-$(CONFIG_TEST1)+= test1///添加這句
雖然 Makefile 中已經包含了,但這樣還是不行。因為當需要配置 ARM 時, ARM 結構下的 Kconfig并沒有包含 test 的 Kconfig 。這樣的話就不會出現在圖形配置界面中,因此在 arch/arm/Kconfig 中添加語句。
2.7.vim arch/arm/Kconfig
1230 menu "Device Drivers"
1231
1232 source "drivers/base/Kconfig"
…..............................................
1328 source "drivers/staging/Kconfig"
1329
1330 source "drivers/test1/Kconfig"
1331
1332 endmenu
大功告成!
這樣, make menuconfig 界面寫的 Driver Devices 下就多了一個 "test1 driver here" 的目錄,里面有一個配置選項 "xiaobai test1 driver" 。
Kconfig 文件的語法在 documentation/kbuild/kconfig-language.txt 文件中有詳細的講解,上面我只是簡單實現了一下 , 但都是皮毛。
==============================================
5. 編譯內核
編譯內核很簡單,只需要配置完畢后執行 make 命令,將指定的文件編譯進內核
bzImage 或者編譯成模塊。
make = make bzImage + make modules
因此如果值編譯內核,即只編譯配置文件中 -y 選項,可以直接用命令
make bzImage
如果值編譯模塊,即只編譯配置文件中的 -m 選項,可以之直接使用命令
make modules
模塊可以編譯當然也可以清除,使用命令
make modules clean
如果只想單獨編譯一個模塊,可以使用命令
make M=drivers/test/ modules // 只單獨編譯 drivers/test 中的 .ko
make M=drivers/test/ modules clean// 清除
上面的是在內核目錄下的操作,但當我寫驅動時,我并不可能在內核目錄下編
寫,但我編譯時卻要依賴內核中的規則和 Makefile ,所以就有了以下的方法,
同時這也是一般的編寫驅動時 Makefile 的格式。
指定內核 Makefile 并單獨編譯
make -C /root/linux-2.6.29 M=`pwd` module
make -C /root/linux-2.6.29 M=`pwd` module clean
//-C指定內核 Makefile 的路徑,可以使用相對路徑。
//-M指定要編譯的文件的路徑,同樣課使用相對路徑。
編譯生成的模塊可以指定存放的目錄
make -C /root/linux-2.6.29 M=`pwd` modules_install INSTALL_MOD_PATH=/nfsroot
=======================================================================
以上都是個人理解,如內核的 Makefile 配置和編譯時一個復雜的過程,我簡單地描述了一下,并不保證一定正確。
錯誤地方,請指正。
總結
以上是生活随笔為你收集整理的linux驱动内核哪个文件夹,linux设备驱动归纳总结(一):内核的相关基础概念...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3年未出险汽车保费反上涨400元 车主懵
- 下一篇: 非对称交易是什么意思