如何在Linux内核中启动初始化过程? [英] How is the init process started in the Linux kernel?

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

问题描述

我试图了解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"是它在内核初始化过程中最后要做的事情之一.函数 kernel_init() init/main.c 中具有逻辑.

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()

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内核中启动初始化过程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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