1:根据任务结构体中的mm.
内核一开始只有内核进程,那用户进程的mm创建在什么时候?内核启动过程中第一个init进程代表用户进行,通过 run_init_process函数:
static int run_init_process(const char *init_filename)
{
const char *const *p;
argv_init[0] = init_filename;
pr_info("Run %s as init process\n", init_filename);
pr_debug(" with arguments:\n");
for (p = argv_init; *p; p++)
pr_debug(" %s\n", *p);
pr_debug(" with environment:\n");
for (p = envp_init; *p; p++)
pr_debug(" %s\n", *p);
return kernel_execve(init_filename, argv_init, envp_init);
}
init进程的mm创建:
kernel_execve
bprm_execve
exec_binprm
search_binary_handler
load_elf_binary
begin_new_exec
exec_mmap
tsk->active_mm = mm;
tsk->mm = mm;
__set_task_comm //修改comm进程名
其它用户启动的进程:
=> exec_mmap
=> begin_new_exec
=> load_elf_binary
=> search_binary_handler
=> exec_binprm
=> bprm_execve
=> do_execveat_common
=> __arm64_sys_execve
=> el0_svc_common.constprop.0
=> do_el0_svc
=> el0_svc
=> el0_sync_handler
=> el0_sync
内核线程创建的时候判断:
__primary_switched
adr_l x5,init_task //将内核第一个线程设置为init_task。此task->mm =NULL ; active_mm = init_mm;
msr sp_el0,x5 //将init_task地址放入sp_el0,此后current 将指向init_task。
start_kernel //执行start_kernel函数
kernel_thread //kernel_init //init线程
run_init_process
kernel_execve // 被exec为systemd ?
kernel_thread //kthreadd .用来创建内核线程
kthread_run最终也需要使用这个函数来创建内核线程
kernel_thread
kernel_clone
copy_process
copy_mm
tsk->mm = NULL;
tsk->active_mm = NULL;
if(!current->mm)
return 0 ;//如果mm为空,则内核线程。保持mm和active_mm为NULL
用户线程...