在2.4(具體哪個版本記不清了)以後的linux核心中引入了一種新的向核心傳遞引數的方法tag標記。核心引數通過乙個靜態的tag鍊錶在啟動的時候傳遞到核心。每個tag的結構為
tag_header
tag_***
其中tag_header為tag頭,表明tag_***的型別和大小,之所以要標識tag_***的型別是因為不同的tag需要不同的處理函式(下文講tagtable的時候會分析到)。tag_header的結構為
struct tag_header
size表示tag的結構大小,tag為表示tag型別的常量。這個靜態的鍊錶必須以tag_header.tag = atag_core開始,並以tag_header.tag = atag_none結束。由於不同的tag所使用的格式可能不盡相同,所以核心又定義了乙個結構tagtable來把tag和相應的操作函式關聯起來
struct tagtable
其中tag為標識入atag_none,atag_core等。parse為處理函式。linux核心將tagtable也組成了乙個靜態的鍊錶放入.taglist.init節中,這是通過__tagtable巨集來實現的
#
define __tag __attribute_used__ __attribute__(
(__section__ (「.taglist.init」)))
#define __tagble(tag,fn)
static
struct tagtable __tagtable_#
#fn __tag =
以處理命令列引數為例:
static
int __init parse_tag_cmdline(
const
struct tag* tag)
__tagtable(atag_cmdline, parse_tag_cmdline)
可以看到parse_tag_cmdline將命令列引數拷貝到default_command_line裡,__tagtable將atag_cmdline和parse_tag_cmdline掛鉤。
以上已經分析了核心和tag相關的兩個重要結構。現在分析具體的實現。核心中定義了一些預設的tags
static
struct init_tags
init_tags __initdata =,,
,,}
上述結構中乙個tag_header和tag_***形成了tag的完整描述,tag_size返回tag_head和tag_***的總大小,在tag_size中我們要注意的是u32*指標加1位址值實際上位址加了4
#define tag_next(t) ((struct tag*)((u32*)(t)+(t)->hdr.size))
#define tag_size(type) ((sizeof(struct tag_header)+sizeof(struct type)) >> 2
tag_size實際上計算的是(tag_head+tag_***)/4。經過進一步的分析還發現每個tag在記憶體中的大小並不是相同的,這一點可以從tag_next看出,tag_next只是將指標移到了下乙個tag的tag_header處,這種記憶體布局更加緊湊。對tag的處理**在arch/arm/setup.c setup_arch裡面。以下是一部分的關鍵**
struct tag *tags =
(struct tag*
)&init_tags;
//tags指向預設的tag鍊錶
……mdesc = setup_machine(machine_arch_type)
;// mdesc包含啟動引數在記憶體中的位址
if( mdesc-
>boot_params )
tags = phys_to_vert(mdesc-
>boot_params)
;// bootloader有傳遞啟動引數到核心
if( tags-
>hdr.tag !
= atag_core )
convert_to_tag_list(tags)
;//如果是舊的啟動引數結構,將其轉成新的tag鍊錶的形式
if( tags-
>hdr.tags !
= atag_core )
tags =
(struct tag*
)&init_tags;
//轉換失敗,使用內建的啟動引數
if( tags-
>hdr.tag =
= atag_core )
*注:2.6.18核心smdk2410
的meminfo
沒有設定
nr_banks
,所以必須在核心的啟動引數裡面傳遞
mem=」memory size」@」memory base address」
,否則系統識別記憶體錯誤,這點從系統的啟動資訊就可以看出來,而且在載入
initrd
的時候也會遇到記憶體溢位的錯誤
static
void __init parse_tags(
const
struct tag* t)
}
parse_tags遍歷tag鍊錶呼叫parse_tag對tag進行處理。parse_tags在tabtable中尋找tag的處理函式(通過tag_header結構中的tag)。
u boot向Linux核心傳遞引數tag原理分析
u boot最主要的功能是引導os,目前對linux支援的相對比較好,引導 的意義不僅僅是拷貝核心,執行核心,還要給核心kernel傳遞板子的相關引數,打個比方,u boot相當於是一名專業功底深厚的 接待員 他會先初始化好一些外圍裝置,比如說串列埠,sdram nand flash mmc等,初始...
Linux核心模組傳遞引數
如果需要向核心模組中傳遞引數,可以使用函式 module param 引數名,引數型別,讀寫許可權 1 引數名稱 不必解釋 2 引數型別 byte,short,short,int,uint,long,ulong,charp,bool,invbool 3 讀寫許可權 一般為s irugo 例子 傳遞乙...
Linux 核心 給模組傳遞引數
對於如何向模組傳遞引數,linux kernel 提供了乙個簡單的框架。其允許驅動程式宣告引數,並且使用者在系統 啟動或模組裝載時為引數指定相應值,在驅動程式裡,引數的用法如同全域性變數。使用下面的巨集時需要包含標頭檔案 moduleparam.h 通過巨集module param 定義乙個模組引數...