嵌入式之路--Linux內存配置解析

內核內存配置解析

原創聲明:作者保留一切權力,轉載請註明出處。

所有資料均來源於互聯網,若侵犯了您的權利,請告知,作者一定修正。

 

一、meminfo變量與結構體

內核在啓動過程中通過一個全局變量‘meminfo’來配置內存。

巧合的是,這個全局變量與它的類型,一個特殊的結構體‘meminfo’同名。

 

變量的定義在

arch/arm/kernel/setup.c

 

static struct meminfo meminfo __initdata = { 0, };

 

這句話表示定義一個作用域是本文件的變量(static),這個變量的類型是個結構體(struct meminfo), 變量的名稱是meminfo,它被定位在data段(__initdata),它同時被初始化({ 0, })。

 

 結構體struct meminfo  聲明在

include/asm-arm/setup.h

 

struct meminfo {

            int nr_banks;

            struct membank bank[NR_BANKS];

};

 

二、內核配置內存的過程

系統對內存的默認配置是通過tag設置的。

 

arch/arm/kernel/setup.c 中事先定義了默認的 tags. 即全局變量 init_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_size(tag_mem32), ATAG_MEM },

            { MEM_SIZE, PHYS_OFFSET }

 

所以 經過 parse_tags(tags) , 初始內存就配置好了.也就是說變量meminfo就有內容了。

它的內容會被用戶自定義的設置所覆蓋,如果有用戶設置的話。

 

用戶可以通過命令行中的mem來定義自己的設置。

   mem=16M@0xC0000000

表明內存大小爲16M 起始地址是0xC000000

<Q001> 這個地址是物理地址還是邏輯地址?

 

[1] linux 2.6內核啓動過程中,是如何得到內存大小的

引用{

arm linux中一般在cmdline或傳遞tag參數中設置, 個別板子在machine_desc.fixup函數中設置. 按順序分別說明:

 

1, 出現順序(內核版本2.6.25.20,下同)

start_kernel()

    ->setup_arch()

        ->mdesc->fixup()

        ->parse_tags()

            ->parse_tag_mem32()

        ->parse_cmdline()

            ->early_mem()

 

2, fixup()函數

這個函數arm平臺用的很少. 我只找到eseries.c, mach-smdk2413.c, mach-vstms.c這幾個arm板子有, smdk2413_fixup()是在bootloader傳遞tag地址與machine_desc預設tag地址(mem_PA+0x100)不同時設置memorystartsize. 如果fixup起作用, 會從tag中把mem tag改爲ATAG_NONE, 後面的"parse_tag_mem32"就沒用了.

 

3, parse_tag_mem32()

該函數定義在"arch/arm/kernel/setup.c". bootloader傳入的mem tag(ATAG_MEM)startsize參數通過"arm_add_memory()"加入到meminfo的最後一個bank. startmemory物理起始地址.

 

4, early_mem()

該函數定義在"arch/arm/kernel/setup.c". 處理cmdline中的"mem=size@start".

如果沒有定義mem起始地址, 使用'PHYS_OFFSET'(arm中應由arm開發板設置)作爲start. early_mem()會覆蓋前面設置的meminfo.

 

}引用

 

三、遺留問題

<Q001> 命令行mem定義的地址是物理地址還是邏輯地址?

<Q002>如果有兩片以上且物理地址不連續的內存應該怎樣定義?

 

四、參考資料

[1] linux 2.6內核啓動過程中,是如何得到內存大小的

http://linux.chinaunix.net/bbs/thread-1062377-1-1.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章