如何在Linux内核中启动init进程?

San*_*yal 7 linux linux-device-driver linux-kernel embedded-linux

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

    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 }
Run Code Online (Sandbox Code Playgroud)

但我无法弄明白

  1. 它将如何执行?

  2. 在哪里安排和

  3. 当我们说我们已经安排了这个init_task任务时,linux内核中的哪些代码行会立即开始执行?它有什么功能吗?

cha*_*nan 11

内核调用"init"作为内核初始化过程中最后的事情之一.该函数kernel_init()在初始化/ main.c中具有逻辑.

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

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

其主要作用机制是调用do_execve()与固定参数argv_init和envp_init.该小精灵文件被解析和初始程序计数器(PC)被设定为每该文件.所有内存管理(mm)页面都映射到磁盘后备存储.代码设置为运行.在计划的初始PC提取时,会生成页面错误,将第一个代码页读入内存.这与任何其他execve()呼叫相同.