天天看点

linux进程创造 - 内核进程初始化及创建1. 内核进程初始化2. 内核进程创建change log

1. 内核进程初始化

1.1 idle/swapper进程 - (pid:0)

内核的第一个进程叫idle进程或者swapper进程,这是初始化阶段从无到有创建的第一个内核进程,每个cpu都有一个进程0,当内核中没有其他进程运行时,就会调用该进程使得cpu处于idle状态,进程描述符为init_task,如下:

(init/init_task.c)

(include/linux/init_task.h)

#define INIT_TASK(tsk)  \
{                                   \
    .state      = 0,                        \
    .stack      = &init_thread_info,                \
    .usage      = ATOMIC_INIT(2),               \
    .flags      = PF_KTHREAD,                   \
    .prio       = MAX_PRIO-20,                  \
    .static_prio    = MAX_PRIO-20,                  \
    .normal_prio    = MAX_PRIO-20,                  \
    .policy     = SCHED_NORMAL,                 \
    .cpus_allowed   = CPU_MASK_ALL,                 \
    .nr_cpus_allowed= NR_CPUS,                  \
    .mm     = NULL,                     \
    .active_mm  = &init_mm,                 \
    .restart_block = {                      \
        .fn = do_no_restart_syscall,                \
    },                              \
    .se     = {                     \
        .group_node     = LIST_HEAD_INIT(tsk.se.group_node),    \
    },                              \
    .rt     = {                     \
        .run_list   = LIST_HEAD_INIT(tsk.rt.run_list),  \
        .time_slice = RR_TIMESLICE,             \
    },                              \
    .tasks      = LIST_HEAD_INIT(tsk.tasks),            \
    INIT_PUSHABLE_TASKS(tsk)                    \
    INIT_CGROUP_SCHED(tsk)                      \
    .ptraced    = LIST_HEAD_INIT(tsk.ptraced),          \
    .ptrace_entry   = LIST_HEAD_INIT(tsk.ptrace_entry),     \
    .real_parent    = &tsk,                     \
    .parent     = &tsk,                     \
    .children   = LIST_HEAD_INIT(tsk.children),         \
    .sibling    = LIST_HEAD_INIT(tsk.sibling),          \
    .group_leader   = &tsk,                     \
    RCU_POINTER_INITIALIZER(real_cred, &init_cred),         \
    RCU_POINTER_INITIALIZER(cred, &init_cred),          \
    .comm       = INIT_TASK_COMM,               \
    .thread     = INIT_THREAD,                  \
    .fs     = &init_fs,                 \
    .files      = &init_files,                  \
    .signal     = &init_signals,                \
    .sighand    = &init_sighand,                \
    .nsproxy    = &init_nsproxy,                \
    .pending    = {                     \
        .list = LIST_HEAD_INIT(tsk.pending.list),       \
        .signal = {{0}}},                   \
    .blocked    = {{0}},                    \
    .alloc_lock = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),     \
    .journal_info   = NULL,                     \
    .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers),      \
    .pi_lock    = __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),    \
    .timer_slack_ns = 50000, /* 50 usec default slack */        \
    .pids = {                           \
        [PIDTYPE_PID]  = INIT_PID_LINK(PIDTYPE_PID),        \
        [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID),       \
        [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),        \
    },                              \
    .thread_group   = LIST_HEAD_INIT(tsk.thread_group),     \
    .thread_node    = LIST_HEAD_INIT(init_signals.thread_head), \
    INIT_IDS                            \
    INIT_PERF_EVENTS(tsk)                       \
    INIT_TRACE_IRQFLAGS                     \
    INIT_LOCKDEP                            \
    INIT_FTRACE_GRAPH                       \
    INIT_TRACE_RECURSION                        \
    INIT_TASK_RCU_PREEMPT(tsk)                  \
    INIT_TASK_RCU_TASKS(tsk)                    \
    INIT_CPUSET_SEQ(tsk)                        \
    INIT_RT_MUTEXES(tsk)                        \
    INIT_PREV_CPUTIME(tsk)                      \
    INIT_VTIME(tsk)                         \
    INIT_NUMA_BALANCING(tsk)                    \
    INIT_KASAN(tsk)                         \
}
           

1.2 init进程 - (pid:1)

init进程主要创建和监控其他运行进程的活动,它由进程0创建,并执行系统调用execve()装入可执行程序init。

内核进程init执行的函数为kernel_init

static int __ref kernel_init(void *unused)
{
    int ret;

    kernel_init_freeable();
    /* need to finish all async __init code before freeing the memory */
    async_synchronize_full();
    free_initmem();
    mark_readonly();
    system_state = SYSTEM_RUNNING;
    numa_default_policy();

    flush_delayed_fput();

    rcu_end_inkernel_boot();

    if (ramdisk_execute_command) {
        ret = run_init_process(ramdisk_execute_command);
        if (!ret)
            return ;
        pr_err("Failed to execute %s (error %d)\n",
               ramdisk_execute_command, ret);
    }

    /*
     * We try each of these until one succeeds.
     *
     * The Bourne shell can be used instead of init if we are
     * trying to recover a really broken machine.
     */
    if (execute_command) {
        ret = run_init_process(execute_command);
        if (!ret)
            return ;
        panic("Requested init %s failed (error %d).",
              execute_command, ret);
    }
    if (!try_to_run_init_process("/sbin/init") ||
        !try_to_run_init_process("/etc/init") ||
        !try_to_run_init_process("/bin/init") ||
        !try_to_run_init_process("/bin/sh"))
        return ;

    panic("No working init found.  Try passing init= option to kernel. "
          "See Linux Documentation/init.txt for guidance.");
}
           

1.3 初始化

在init/main.c的start_kernel函数中执行内核进程的初始化

linux进程创造 - 内核进程初始化及创建1. 内核进程初始化2. 内核进程创建change log

2. 内核进程创建

创建内核进程调用函数kernel_thread

(kernel/fork.c)

pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
    return _do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
        (unsigned long)arg, NULL, NULL, );
}
           

change log

date content linux
2016.11.27 初创 linux4.6.3

继续阅读