天天看點

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

繼續閱讀