Linux内核中init进程是如何启动的? [英] How is the init process started in the Linux kernel?

查看:24
本文介绍了Linux内核中init进程是如何启动的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解 linux 内核中的 init 进程,它是第一个进程,并使用 INIT_TASK 宏静态初始化.

I am trying to understand the init process in the linux kernel which is the first process and is statically initialized with the INIT_TASK macro.

    161 #define INIT_TASK(tsk)  
    162 {                                                                       
    163         .state          = 0,                                            
    164         .stack          = &init_thread_info,                            
    165         .usage          = ATOMIC_INIT(2),                               
    166         .flags          = PF_KTHREAD,                                   
    167         .prio           = MAX_PRIO-20,                                  
    168         .static_prio    = MAX_PRIO-20,                                  
    169         .normal_prio    = MAX_PRIO-20,                                  
    170         .policy         = SCHED_NORMAL,                                 
    171         .cpus_allowed   = CPU_MASK_ALL,                                 
    172         .nr_cpus_allowed= NR_CPUS,                                      
    173         .mm             = NULL,                                         
    174         .active_mm      = &init_mm,                                     
    175         .se             = {                                             
    176                 .group_node     = LIST_HEAD_INIT(tsk.se.group_node),    
    177         },                                                              
    178         .rt             = {                                             
    179                 .run_list       = LIST_HEAD_INIT(tsk.rt.run_list),      
    180                 .time_slice     = RR_TIMESLICE,                         
    181         },                                                              
    182         .tasks          = LIST_HEAD_INIT(tsk.tasks),                    
    183         INIT_PUSHABLE_TASKS(tsk)                                        
    184         INIT_CGROUP_SCHED(tsk)                                          
    185         .ptraced        = LIST_HEAD_INIT(tsk.ptraced),                  
    186         .ptrace_entry   = LIST_HEAD_INIT(tsk.ptrace_entry),             
    187         .real_parent    = &tsk,                                         
    188         .parent         = &tsk,                                         
    189         .children       = LIST_HEAD_INIT(tsk.children),                 
    190         .sibling        = LIST_HEAD_INIT(tsk.sibling),                  
    191         .group_leader   = &tsk,                                         
    192         RCU_POINTER_INITIALIZER(real_cred, &init_cred),                 
    193         RCU_POINTER_INITIALIZER(cred, &init_cred),                      
    194         .comm           = INIT_TASK_COMM,                               
    195         .thread         = INIT_THREAD,                                  
    196         .fs             = &init_fs,                                     
    197         .files          = &init_files,                                  
    198         .signal         = &init_signals,                                
    199         .sighand        = &init_sighand,                                
    200         .nsproxy        = &init_nsproxy,                                
    201         .pending        = {                                             
    202                 .list = LIST_HEAD_INIT(tsk.pending.list),               
    203                 .signal = {{0}}},                                       
    204         .blocked        = {{0}},                                        
    205         .alloc_lock     = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),         
    206         .journal_info   = NULL,                                         
    207         .cpu_timers     = INIT_CPU_TIMERS(tsk.cpu_timers),              
    208         .pi_lock        = __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),        
    209         .timer_slack_ns = 50000, /* 50 usec default slack */            
    210         .pids = {                                                       
    211                 [PIDTYPE_PID]  = INIT_PID_LINK(PIDTYPE_PID),            
    212                 [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID),           
    213                 [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),            
    214         },                                                              
    215         .thread_group   = LIST_HEAD_INIT(tsk.thread_group),             
    216         INIT_IDS                                                        
    217         INIT_PERF_EVENTS(tsk)                                           
    218         INIT_TRACE_IRQFLAGS                                             
    219         INIT_LOCKDEP                                                    
    220         INIT_FTRACE_GRAPH                                               
    221         INIT_TRACE_RECURSION                                            
    222         INIT_TASK_RCU_PREEMPT(tsk)                                      
    223         INIT_CPUSET_SEQ                                                 
    224         INIT_VTIME(tsk)                                                 
    225 }

但我无法弄清楚

  1. 它将如何执行?

  1. how it will be executed?

预定地点和

当我们说我们已经安排了这个 init_task 任务时,linux 内核中的哪些代码行会立即开始执行?有没有它调用的函数?

which lines of code in the linux kernel start executing immediately when we say we have scheduled this init_task task? Is there any function which it calls?

推荐答案

内核调用init"是它在内核初始化期间所做的最后一件事.函数 init/main.c 中的 kernel_init() 有逻辑.

The kernel calls "init" as one of the very last things it does during kernel initialization. The function kernel_init() in init/main.c has the logic.

您会注意到内核尝试了四种不同的 init 组合,并期望其中一种成功.您还会注意到,您可以通过提供内核命令行参数init"来覆盖内核在启动时执行的内容.因此,您可以说,例如,内核命令行上的 init=/bin/mystartup 并启动​​您自己的自定义应用程序,而不是默认的/sbin/init.另请注意,在大多数现代系统,甚至嵌入式系统中,/sbin/init 是指向真正可执行文件的软链接.

You will notice that the kernel tries four different combinations of init, and expects one of them to succeed. You will also notice that you can override what the kernel executes on startup by feeding the kernel command line parameter "init". So, you can say, for example, init=/bin/mystartup on the kernel command line and start your own custom application instead of the default /sbin/init. Notice also that on most modern systems, even embedded systems, /sbin/init is a soft link that points to the real executable.

为了更一般地回答你的问题,研究这个源文件 (main.c),你可以看到 Linux 内核初始化的几乎所有细节,在低级汇编和平台初始化之后,这超出了教育价值,你不应该接触或关心太多.

To more generally answer your question, study this source file (main.c) you can see virtually all of the details of Linux kernel initialization, after the low-level assembly stuff and platform initialization, which, beyond the educational value, you shouldn't have to touch nor care about much.

主要机制是调用do_execve()argv_initenvp_init 的固定参数.解析 elf 文件并根据文件设置初始 程序计数器 (PC).所有内存管理 (mm) 页面都映射到磁盘后备存储.代码设置为运行.在预定的初始 PC 提取上,会生成一个页面错误,将第一个代码页读入内存.这与任何其他 execve() 调用相同.

The main mechanism is to call do_execve() with fixed arguments of argv_init and envp_init. The elf file is parsed and initial program counter (PC) is set as per the file. All memory management (mm) pages are mapped to the disks backing store. The code is set to run. On the initial PC fetch when it is scheduled, a page fault is generated which reads the first code page into memory. This is the same as any other execve() call.

这篇关于Linux内核中init进程是如何启动的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆