1:根据任务结构体中的mm.

内核线程和用户进程的区别(task_struct)_进程名

内核一开始只有内核进程,那用户进程的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
				用户线程...