關于嵌入式設備上的Linux 系統開發
根據可用的系統資源和引導裝載程序的功能,內核可以編譯成 vmlinux、Image 或 zImage。vmlinux 和 zImage 之間的主要區別在于 vmlinux是實際的(未壓縮的)可執行文件,而 zImage是或多或少包含相同信息的自解壓壓縮文件 D 只是壓縮它以處理(通常是 Intel 強制的)640 KB 引導時間的限制。有關所有這些的權威性解釋,請參閱 Linux Magazine的文章“Kernel Configuration: dealing with the unexpected”(請參閱 參考資料)。
內核鏈接和裝入
一旦為目標系統編譯了內核后,通過使用引導裝載程序(它已經被裝入到目標的閃存中),內核就被裝入到目標系統的內存(在 DRAM 中或者在閃存中)。通過使用串行、USB 或以太網端口,引導裝載程序與主機通信以將內核傳送到目標的閃存或 DRAM 中。在將內核完全裝入目標后,引導裝載程序將控制傳遞給裝入內核的地址。
內核可執行文件由許多鏈接在一起的對象文件組成。對象文件有許多節,如文本、數據、init 數據、bass 等等。這些對象文件都是由一個稱為 鏈接器腳本的文件鏈接并裝入的。這個鏈接器腳本的功能是將輸入對象文件的各節映射到輸出文件中;換句話說,它將所有輸入對象文件都鏈接到單一的可執行文件中,將該可執行文件的各節裝入到指定地址處。 vmlinux.lds是存在于 arch/
清單 2. 典型的 vmlinux.lds 文件
output_ARCH(
ENTRY(stext) /* stext is the kernel entry point */
SECTIONS /* SECTIONS command describes the layout
of the output file */
{
. = TEXTADDR; /* TEXTADDR is LMA for the kernel */
.init : { /* Init code and data*/
_stext = .; /* First section is stext followed
by __init data section */
__init_begin = .;
*(.text.init)
__init_end = .;
}
.text : { /* Real text segment follows __init_data section */
_text = .;
*(.text)
_etext = .; /* End of text section*/
}
.data :{
_data=.; /* Data section comes after text section */
*(.data)
_edata=.;
} /* Data section ends here */
.bss : { /* BSS section follows symbol table section */
__bss_start = .;
*(.bss)
_end = . ; /* BSS section ends here */
}
}
LMA 是裝入模塊地址;它表示將要裝入內核的目標虛擬內存中的地址。 TEXTADDR 是內核的虛擬起始地址,并且在 arch/
一旦引導裝載程序將內核復制到閃存或 DRAM 中,內核就被重新定位到 TEXTADDR — 它通常在 DRAM 中。然后,引導裝載程序將控制轉給這個地址,以便內核能開始執行。
參數傳遞和內核引導
stext 是內核入口點,這意味著在內核引導時將首先執行這一節下的代碼。它通常用匯編語言編寫,并且通常它在 arch/
start_kernel 調用 setup_arch 作為執行的第一步,在其中完成特定于體系結構的設置。這包括初始化硬件寄存器、標識根設備和系統中可用的 DRAM 和閃存的數量、指定系統中可用頁面的數目、文件系統大小等等。所有這些信息都以參數形式從引導裝載程序傳遞到內核。
將參數從引導裝載程序傳遞到內核有兩種方法:parameter_structure 和標記列表。在這兩種方法中,不贊成使用參數結構,因為它強加了限制:指定在內存中,每個參數必須位于 param_struct 中的特定偏移量處。最新的內核期望參數作為標記列表的格式來傳遞,并將參數轉化為已標記格式。 param_struct 定義在 include/asm/setup.h 中。它的一些重要字段是:
清單 3. 樣本參數結構
struct param_struct {
unsigned long page_size; /* 0: Size of the page */
unsigned long nr_pages; /* 4: Number of pages in the System */
unsigned long ramdisk /* 8: ramdisk size */
unsigned long rootdev; /* 16: number representing the root device */
unsigned long initrd_start; /* 64: starting address of initial ramdisk */
/* This can be either in flash/dram */
unsigned long initrd_size; /* 68: size of initial ramdisk */
}
請注意:這些數表示定義字段的參數結構中的偏移量。這意味著如果引導裝載程序將參數結構放置在地址 0xc0000100,那么 rootdev 參數將放置在 0xc0000100 + 16,initrd_start 將放置在 0xc0000100 + 64 等等 D 否則,內核將在解釋正確的參數時遇到困難。
正如上面提到的,因為從引導裝載程序到內核的參數傳遞會有一些約束條件,所以大多數 2.4.x 系列內核期望參數以已標記的列表格式傳遞。在已標記的列表中,每個標記由標識被傳遞參數的 tag_header 以及其后的參數值組成。標記列表中標記的常規格式可以如下所示:
清單 4. 樣本標記格式。內核通過
#define
struct
u32
u32
};
/* Example tag for passing memory information */
#define ATAG_MEM 0x54410002 /* Magic number */
struct tag_mem32 {
u32 size; /* size of memory */
u32 start; /* physical start address of memory*/
linux操作系統文章專題:linux操作系統詳解(linux不再難懂)








評論