How is the init process started in the Linux kernel?

14,318

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.

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.

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.

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.

Share:
14,318

Related videos on Youtube

Sandeep Tayal
Author by

Sandeep Tayal

Updated on September 19, 2022

Comments

  • Sandeep Tayal
    Sandeep Tayal over 1 year

    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 }
    

    But I am not able to figure out

    1. how it will be executed?

    2. Where it is scheduled and

    3. 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?

  • Sandeep Tayal
    Sandeep Tayal over 10 years
    Thanks Challinan for your answer. very nice explanation. I am more looking towards which instructions or which lines of code init actually executes.I know it is statically allocated and this structure as initialized by INIT_TASK is pushed to execution by scheduler.
  • artless noise
    artless noise over 10 years
    @SandeepTayal What exactly is not clear? The init tasks code path is the same as any execve() program call; the kernel used do_execve() directly which is the end-point of an execve() syscall.
  • Sridhar Sarnobat
    Sridhar Sarnobat about 2 years
    init -> ../bin/busybox (buildroot based on Ubuntu) or /sbin/init -> /lib/systemd/systemd (my "real" Ubuntu installation)