Linuxカーネルパラメータ伝達Tag

11750 ワード

2.4以降のLinuxカーネルには、新しいカーネルにパラメータを渡す方法tagタグが導入されています.カーネルパラメータは、静的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の処理関数を検索する.