日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux内核参数传递Tag

發布時間:2023/12/10 linux 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux内核参数传递Tag 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在2.4(具體哪個版本記不清了)以后的Linux內核中引入了一種新的向內核傳遞參數的方法tag標記。內核參數通過一個靜態的tag鏈表在啟動的時候傳遞到內核。每個tag的結構為

???????????????????+-----------+

????????????????????tag_header

???????????????????+-----------+

??????????????????? tag_xxx

???????????????????+-----------+

?

其中tag_header為tag頭,表明tag_xxx的類型和大小,之所以要標識tag_xxx的類型是因為不同的tag需要不同的處理函數(下文講tagtable的時候會分析到)。tag_header的結構為

struct tag_header
{
????int size;
????int tag;
}

size表示tag的結構大小,tag為表示tag類型的常量。這個靜態的鏈表必須以tag_header.tag = ATAG_CORE開始,并以tag_header.tag = ATAG_NONE結束。由于不同的tag所使用的格式可能不盡相同,所以內核又定義了一個結構tagtable來把tag和相應的操作函數關聯起來

struct tagtable
{
???????u32 tag;
???????int (*parse)(const struct tag*);
}

?

?

其中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 = {tag, fn}

以處理命令行參數為例:

static int __init parse_tag_cmdline(const struct tag* tag)
{
????strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
}
__tagtable(ATAG_CMDLINE, parse_tag_cmdline)

?

?

可以看到parse_tag_cmdline將命令行參數拷貝到default_command_line里,__tagtable將ATAG_CMDLINE和parse_tag_cmdline掛鉤。

以上已經分析了內核和tag相關的兩個重要結構。現在分析具體的實現。內核中定義了一些默認的tags

static struct init_tags
{
???????struct tag_header hdr1;
???????struct tag_core core;
???????struct tag_header hdr2;
???????struct tag_mem32 mem;
???????struct tag_header hdr3;
}init_tags __initdata = {
???????{ tag_size(tag_core), ATAG_CORE },
???????{ 1, PAGE_SIZE, 0xff },
???????{ tag_size(tag_mem32), ATAG_MEM },
???????{ MEM_SIZE, PHYS_OFFSET },
???????{ 0, ATAG_NONE }
}

上述結構中一個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鏈表
……
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 )
{
???????if( meminfo.nr_banks != 0 )
??????????????squash_mem_tags(tags);//如果在meminfo中有配置內存tag則跳過對內存tag的處理
???????parse_tags(tags);
}


*:2.6.18內核smdk2410meminfo沒有設置nr_banks,所以必須在內核的啟動參數里面傳遞mem=”memory size”@”memory base address”,否則系統識別內存錯誤,這點從系統的啟動信息就可以看出來,而且在加載initrd的時候也會遇到內存溢出的錯誤

?

?

static void __init parse_tags(const struct tag* t)
{
???????for(; t->hdr.size; t=tag_next(t))
?????? {
?????????? if( !parse_tag(t))
??????????????printk();
?????? }
}

parse_tags遍歷tag鏈表調用parse_tag對tag進行處理。parse_tags在tabtable中尋找tag的處理函數(通過tag_header結構中的tag)。

總結

以上是生活随笔為你收集整理的Linux内核参数传递Tag的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。