Linuxカーネルパラメータ伝達Tag
2.4以降のLinuxカーネルには、新しいカーネルにパラメータを渡す方法tagタグが導入されています.カーネルパラメータは、静的tagチェーンテーブルを介して起動時にカーネルに渡されます.各tagの構造は
+-----------+
tag_header
+-----------+
tag_xxx
+-----------+
ここでtag_ヘッダはtagヘッダであり、tag_を示すxxxのタイプとサイズ、tag_を識別する理由xxxのタイプは、異なるtagが異なる処理関数を必要とするためである(以下、tagtableの場合に分析する).tag_ヘッダの構造は
sizeはtagの構造サイズを表し、tagはtagのタイプを表す定数である.この静的チェーンテーブルはtag_header.tag = ATAG_COREで始まり、tag_header.tag = ATAG_NONE終了.異なるtagで使用されるフォーマットが異なる可能性があるため、カーネルはtagと対応する操作関数を関連付ける構造tagtableを定義します.
ここでtagはATAGを識別するNONE,ATAG_COREなど.parseは処理関数です.Linuxカーネルはtagtableも構成する静的チェーンテーブルを入れる.taglist.Initセクションでは、これは_tagtableマクロで実現
コマンドラインパラメータの処理を例にとります.
parse_が見えますtag_cmdlineコマンドラインパラメータをdefault_にコピーcommand_lineの中、_tagtableはATAGをCMDLINEとparse_tag_cmdlineフック.
以上,カーネルとtagに関連する2つの重要な構造を解析した.具体的な実装を分析します.カーネルにはデフォルトのtagsが定義されています
上記構成の1つtag_ヘッダーとtag_xxxはtagの完全な説明を形成し、tag_sizeはtag_を返しますheadとtag_xxxの合計サイズはtag_sizeで注意したいのは、u 32*ポインタに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_に移動しただけですヘッダーでは、このメモリレイアウトがよりコンパクトです.tagに対する処理コードはarch/arm/setup.c setup_Archの中.以下は一部のキーコードです
*注:2.6.18カーネルsmdk 2410のmeminfoにnr_が設定されていませんbanksなので、カーネルの起動パラメータにmem=“memory size”@“memory base address”を渡さなければなりません.そうしないと、システムがメモリエラーを認識することは、システムの起動情報からわかります.また、initrdをロードするときにメモリオーバーフローのエラーに遭遇します.
parse_tagsはtagチェーンテーブル呼び出しparse_を遍歴するtagはtagを処理する.parse_tagsは、tabtable(tag_header構造のtagを介して)tagの処理関数を検索する.
+-----------+
tag_header
+-----------+
tag_xxx
+-----------+
ここでtag_ヘッダはtagヘッダであり、tag_を示すxxxのタイプとサイズ、tag_を識別する理由xxxのタイプは、異なるtagが異なる処理関数を必要とするためである(以下、tagtableの場合に分析する).tag_ヘッダの構造は
struct tag_header
{
int size;
int tag;
}
sizeはtagの構造サイズを表し、tagはtagのタイプを表す定数である.この静的チェーンテーブルはtag_header.tag = ATAG_COREで始まり、tag_header.tag = ATAG_NONE終了.異なるtagで使用されるフォーマットが異なる可能性があるため、カーネルはtagと対応する操作関数を関連付ける構造tagtableを定義します.
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に関連する2つの重要な構造を解析した.具体的な実装を分析します.カーネルにはデフォルトの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 }
}
上記構成の1つtag_ヘッダーとtag_xxxはtagの完全な説明を形成し、tag_sizeはtag_を返しますheadとtag_xxxの合計サイズはtag_sizeで注意したいのは、u 32*ポインタに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_に移動しただけですヘッダーでは、このメモリレイアウトがよりコンパクトです.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カーネルsmdk 2410のmeminfoに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_header構造のtagを介して)tagの処理関数を検索する.