雖說前文分析記憶體管理框架構建的實作,提到了find_zone_movable_pfns_for_nodes(),但這里不準備復述什么,僅針對required_movablecore和required_kernelcore做一個補充,
以required_movablecore為例,代碼中沒有很清晰地表明該值從何而來,僅有一處cmdline_parse_movablecore()疑似賦值的實作:
【file:/mm/page_alloc.c】
/*
* movablecore=size sets the amount of memory for use for allocations that
* can be reclaimed or migrated.
*/
static int __init cmdline_parse_movablecore(char *p)
{
return cmdline_parse_core(p, &required_movablecore);
}
而其中cmdline_parse_core()實作:
【file:/mm/page_alloc.c】
static int __init cmdline_parse_core(char *p, unsigned long *core)
{
unsigned long long coremem;
if (!p)
return -EINVAL;
coremem = memparse(p, &p);
*core = coremem >> PAGE_SHIFT;
/* Paranoid check that UL is enough for the coremem value */
WARN_ON((coremem >> PAGE_SHIFT) > ULONG_MAX);
return 0;
}
可以推測其值是由此而來,繼而可以找到:
【file:/mm/page_alloc.c】
early_param("movablecore", cmdline_parse_movablecore);
這是一個函式注冊宏,該宏展開后:
static const char __setup_str_cmdline_parse_movablecore[] __attribute__ ((__section__(".init.rodata"))) __attribute__((aligned(1))) = "movablecore"; static struct obs_kernel_param __setup_cmdline_parse_movablecore __attribute__((__used__)) __attribute__ ((__section__(".init.setup"))) __attribute__((aligned((sizeof(long))))) = { __setup_str_cmdline_parse_movablecore, cmdline_parse_movablecore, 1 }
由此借用于__section__屬性定義,編譯器通過arch/x86/kernel/vmlinux.lds鏈接腳本把__setup_cmdline_parse_movablecore放置在.init.setup段中,
注冊的函式將會在do_early_param()中呼叫,相關代碼:
【file:/init/main.c】
/* Check for early params. */
static int __init do_early_param(char *param, char *val, const char *unused)
{
const struct obs_kernel_param *p;
for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && parameq(param, p->str)) ||
(strcmp(param, "console") == 0 &&
strcmp(p->str, "earlycon") == 0)
) {
if (p->setup_func(val) != 0)
pr_warn("Malformed early option '%s'\n", param);
}
}
/* We accept everything at this stage. */
return 0;
}
可以看到借助于__setup_start和__setup_end的范圍標記,將遍歷.init.setup段中的排布的obs_kernel_param結構體,找到匹配的字串及early成員為true的情況下,將會呼叫其中的setup_func鉤子函式,由此將對應資料初始化,
do_early_param()函式在初始化時的呼叫關系:
do_early_param()函式在初始化時的呼叫關系:
start_kernel()
->setup_arch()
->parse_early_param()
->parse_early_options()
->parse_args()
->parse_one()
->do_early_param()
這里只能說明required_movablecore和required_kernelcore在何處初始化的,而其值的由來呢?其值通過入參傳遞,在parse_early_param()函式中通過strlcpy()來自于boot_command_line全域變數,而boot_command_line早期則是在/arch/x86/kernel/head_32.s的初始化中來自于boot_params,具體 do_early_param()處理的資料來自于grub.cfg,也就是說required_movablecore和required_kernelcore也是來自于此,
好了,暫且分析至此,避免走偏了,該文也是一時好奇鉆研了一下,記之以作備忘,
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/36213.html
標籤:嵌入式
