走遍千山萬水,終於找到了你。
void free_initmem(void)
{
free_init_pages("unused kernel",
(unsigned long)(&__init_begin),
(unsigned long)(&__init_end));
}
啥也不說了,看這個函數名大家就知道是釋放啟動過程中使用的內存空間的。
static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
在看內存管理的代碼中,說memblock使用的內存在啟動後會又內核回收,繼續作為內核可以使用的內存。引發了我一點點的好奇心。 話說內核也是像我們貧下中農一樣,挺省吃儉用的嘛。
從代碼上看,和普通變量定義時的差異就是這個後綴修飾,__initdata_memblock。
#ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
#define __init_memblock __meminit
#define __initdata_memblock __meminitdata
#else
#define __init_memblock
#define __initdata_memblock
#endif
看來這個還得在內核配置上有所配置才能做到省吃儉用。感覺和人生一樣,有的娃出生的時候含著金鑰匙,完全不在乎那麼點內存;而有的就要默默執行hard模式咯。
作為窮苦的孩子,咱還是學習學習hard模式是怎麼個玩兒的哈
#define __meminitdata __section(.meminit.data)
ok,原來就是把這個數據結構定義在了一個叫 .meminit.data的區域。
區域(section)這個高級貨大家請自行搜索 elf section哈,因為我也不大記得了。還是不要誤導了大家。
此處略過若干字,在include/asm-generic/vmlinux.lds.h文件中,有如下定義
#if defined(CONFIG_MEMORY_HOTPLUG)
#define MEM_KEEP(sec) *(.mem##sec)
#define MEM_DISCARD(sec)
#else
#define MEM_KEEP(sec)
#define MEM_DISCARD(sec) *(.mem##sec)
#endif
/* init and exit section handling */
#define INIT_DATA \
*(.init.data) \
MEM_DISCARD(init.data) \
KERNEL_CTORS() \
...
#define INIT_DATA_SECTION(initsetup_align) \
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { \
INIT_DATA \
INIT_SETUP(initsetup_align) \
INIT_CALLS \
CON_INITCALL \
SECURITY_INITCALL \
INIT_RAM_FS \
}
我猜你已經看出點什麼來了,如果沒用猜出來那再看上述代碼一百遍。。。
哦,忘了說了,這裡有個東西叫 “gcc鏈接腳本”,大家請先自行搜之 -_-!
高興得太早了,剛才一路順溜得找到了INIT_DATA_SECTION(),然後,就不知道然後了。。。
關鍵時候注釋起到了不可忽視的作用。所以說,寫代碼注釋很重要。
* SECTIONS
* {
* . = START;
* __init_begin = .;
* HEAD_TEXT_SECTION
* INIT_TEXT_SECTION(PAGE_SIZE)
* INIT_DATA_SECTION(...)
* PERCPU_SECTION(CACHELINE_SIZE)
* __init_end = .;
*
* ...
* }
原來啟動階段可以釋放的內存不僅僅是內存初始化相關的部分,還包括了其他好多東西。嗯,又那麼深入了一點點~
好了,你看這裡和最開始的free_initmem()有沒有點眼熟呢?
我相信你會發現的:)
好了,今天就到這裡,希望對你有幫助~