Linux啟動過程中硬件模塊是如何加載的?
出處:互聯(lián)網(wǎng) 發(fā)布于:2011-09-04 12:31:40
閱讀Linux內(nèi)核啟動代碼的直接動力是我想編寫RTL8019AS的網(wǎng)卡驅(qū)動程序(2.4.18內(nèi)核只支持了CS8900A)。既然要寫驅(qū)動,我就想知道它是怎樣被加載的,好奇心驅(qū)使我先去弄清楚這個問題。
拿到2.4.18的軟件包,一萬多個文件,不知如何下手。所幸的是手頭有三件工具助我入門:
1、一塊移植好linux的開發(fā)板,通過它可以看到linux啟動過程打印的消息。
2、google,網(wǎng)上關(guān)于linux的資料真是太多了!
3、Windows文件搜索引擎,通過它可以知道在那些文件中打印出那些消息。
很快,就找到了linux啟動的總的入口,/arch/arm/boot/compressed/head.s。
start:
.type start,#functiON
.rept 8
mov r0,r0
.endr
……
head.s完成的工作主要是底層寄存器、MMU的一些設定以及kernel的解壓縮。匯編文件中調(diào)用的C代碼大多位于該目錄下misc.c文件,例如:decompress_kernel。
head執(zhí)行完畢后跳到start_kernel(),這個函數(shù)位于文件/init/main.c中。
在start_kernel中,依次執(zhí)行各個初始話函數(shù),直到rest_init(),在這個函數(shù)里啟動了一個init線程,而主線程自己則進入了IDLE狀態(tài)。
在這個函數(shù)里面,先lock_kernel,然后調(diào)用do_basic_setup,在這個函數(shù)里面又是一堆的初始化,有一個函數(shù)要注意:do_initcalls??纯此闪耸裁矗簊tatic void __init do_initcalls(void){initcall_t *call;call = &__initcall_start;do {(*call)( );call ;} while (call < &__initcall_end);/* Make sure there is no pending stuff from the initcall sequence */flush_scheduled_tasks();}
我們所關(guān)心的外圍模塊的驅(qū)動被這一段程序加載的原因:
首先看__initcall_start和__initcall_end,找遍了所有C代碼,沒有它們的定義。后來在vmlinux-armv.lds.in文件中找到了它們:
__initcall_start = .;*(。initcall.init)__initcall_end = .;這個文件是和link相關(guān)的文件,它決定代碼在load環(huán)境中的位置,就好比ADS中的scf文件。先看。initcall.init的含義,它在/include/linux/init.h中定義:
#define __init_call __attribute__ ((unused,__section__ (".initcall.init ")))參考GCC說明,這段話的意思就是說所有以__init_call前綴定義的函數(shù)在鏈接過程中都放到名字為。initcall.init的段(section)里面。如果我們給一個函數(shù)冠以__init_call,那么它在編譯鏈接的時候就會放到。initcall.init這個段里面。
那么要注冊的外圍模塊的初始化程序是不是都是定義成__init_call類型的呢?查看各個模塊我們會發(fā)現(xiàn)其初始化函數(shù)x會被定義成為module_init(x),在/include/linux/init.h中它定義如下:
#define module_init(x) __initcall(x);#define __initcall(fn) static initcall_t __initcall_##fn __init_call = fn這段代碼說module_init(x)等價于__initcall(x),而__initcall(x)表示函數(shù)x是靜態(tài)的具有__init_call性質(zhì)的函數(shù),因此在鏈接時,它會被放在 initcall.init 段中。只要x函數(shù)運行起來,就可以注冊設備、中斷入口、中斷服務函數(shù)了。
明白了設備是如何被加載以后,要明白怎么樣把一個模塊的驅(qū)動程序加載到內(nèi)核里面呢?make menuconfig,把對應設備打開。看看make menuconfig前后哪些文件的修改日期發(fā)生了變化?找到了一點,/scripts下的文件是用來支持各種config模式的(當然包括menuconfig),代碼在Kconfig中。在每個驅(qū)動設備的文件夾下(比如net,mtd)都有一個叫config.in的文件,這些文件定義了我們在menuconfig畫面中看到的目錄結(jié)構(gòu)與選項。
看看這兩個文件:。/config和/include/linux/ autoconf.h。我們做完menuconfig以后,所有改動就反映到了這兩個文件中,這兩個文件的內(nèi)容是一致的。在我們做編譯的過程中,頂層的makefile文件從autoconf.h文件中讀取各項宏定義然后傳遞給子一層的makefile,這些makefile根據(jù)宏定義選擇那些。o文件被鏈接進來加到內(nèi)核中。
清楚了這些以后我就知道怎么給8019添加驅(qū)動了,yy一下:
1、首先要有驅(qū)動程序代碼,8019.c
2、修改net目錄下的config.in文件中添加一項,dep_tristate ' RTL8019 support' CONFIG_RTL8019 $CONFIG_ISA
3、打開menuconfig,將RTL8019 support選擇y,保存后autoconf文件中應該就有了一個宏定義:#define CONFIG_RTL8019
4、打開net目錄下的makefile,添加:obj-$( CONFIG_RTL8019) = 8019.o
5、make dep; make zImage;完成。
注:在menuconfig中選擇 m 和 y 的區(qū)別:
y: 模塊驅(qū)動編譯到內(nèi)核中,啟動時自動加載m:模塊會被編譯,但是不會被編譯到內(nèi)核中,只是生成。o文件,我們可以收集這些。o文件做到linux的文件系統(tǒng)中,然后用insmod實現(xiàn)動態(tài)加載。
版權(quán)與免責聲明
凡本網(wǎng)注明“出處:維庫電子市場網(wǎng)”的所有作品,版權(quán)均屬于維庫電子市場網(wǎng),轉(zhuǎn)載請必須注明維庫電子市場網(wǎng),http://www.hbjingang.com,違反者本網(wǎng)將追究相關(guān)法律責任。
本網(wǎng)轉(zhuǎn)載并注明自其它出處的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點或證實其內(nèi)容的真實性,不承擔此類作品侵權(quán)行為的直接責任及連帶責任。其他媒體、網(wǎng)站或個人從本網(wǎng)轉(zhuǎn)載時,必須保留本網(wǎng)注明的作品出處,并自負版權(quán)等法律責任。
如涉及作品內(nèi)容、版權(quán)等問題,請在作品發(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。
- ARM技術(shù)架構(gòu)與應用開發(fā)實踐指南2026/1/6 10:40:19
- 嵌入式實時操作系統(tǒng)(RTOS)選型與移植技術(shù)指南2025/12/31 10:42:31
- 工業(yè)嵌入式系統(tǒng):通信接口技術(shù)選型與抗干擾設計實踐2025/12/15 14:36:53
- 深入解析嵌入式 OPENAMP 框架:開啟異核通信新時代2025/7/22 16:27:29
- 一文快速了解OPENWRT基礎(chǔ)知識2025/7/14 16:59:04









