Linux内核参数传递Tag
???????????????????+-----------+
????????????????????tag_header
???????????????????+-----------+
??????????????????? tag_xxx
???????????????????+-----------+
?
其中tag_header為tag頭,表明tag_xxx的類型和大小,之所以要標識tag_xxx的類型是因為不同的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”))) |
以處理命令行參數為例:
| static int __init parse_tag_cmdline(const struct tag* tag) |
?
?
可以看到parse_tag_cmdline將命令行參數拷貝到default_command_line里,__tagtable將ATAG_CMDLINE和parse_tag_cmdline掛鉤。
以上已經分析了內核和tag相關的兩個重要結構。現在分析具體的實現。內核中定義了一些默認的tags
| static struct init_tags |
上述結構中一個tag_header和tag_xxx形成了tag的完整描述,tag_size返回tag_head和tag_xxx的總大小,在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_xxx)/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鏈表 |
*注: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)。
總結
以上是生活随笔為你收集整理的Linux内核参数传递Tag的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一次办信用卡被拒绝怎么办
- 下一篇: Linux下,sqlite简单实例