Linux idle进程创建过程(kernel 4.14)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rikeyone/article/details/84029241

idle进程是内核创建的第一个进程,也常常被叫做swapper 进程:


asmlinkage __visible void __init start_kernel(void)
{
    char *command_line;
    char *after_dashes;

    set_task_stack_end_magic(&init_task);

idle进程也是唯一一个不是通过fork产生的进程,他是静态定义的一个进程,init_task就是它的任务结构体。在start_kernel函数的最后:

asmlinkage __visible void __init start_kernel(void)
{
......

/* Do the rest non-__init'ed, we're now alive */
rest_init();

}

rest_init函数中会创建我们系统的第一个用户空间进程,那就是大名鼎鼎的pid为1的init进程。init进程是所有用户空间进程的祖先进程,而idle进程是所有进程的祖先进程。



static noinline void __ref rest_init(void)

{

    struct task_struct *tsk;

    int pid;

    

    rcu_scheduler_starting();

    /*

     * We need to spawn init first so that it obtains pid 1, however

     * the init task will end up wanting to create kthreads, which, if

     * we schedule it before we create kthreadd, will OOPS.

     */

    pid = kernel_thread(kernel_init, NULL, CLONE_FS);


 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();
     ftrace_free_init_mem();
     free_initmem();
     mark_readonly();
     system_state = SYSTEM_RUNNING;
     numa_default_policy();
     rcu_end_inkernel_boot();

     if (ramdisk_execute_command) {
         ret = run_init_process(ramdisk_execute_command);
         if (!ret)
             return 0;
         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 0;

         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 0;

 

     panic("No working init found.  Try passing init= option to kernel. "




在init进程创建完成后,该进程还会创建kthreadd进程,最后进入do_idle,也就是我们所说的idle进程所做的事情,让cpu 进入idle状态。

void cpu_startup_entry(enum cpuhp_state state)
{
    /*

     * This #ifdef needs to die, but it's too late in the cycle to

     * make this generic (arm and sh have never invoked the canary

     * init for the non boot cpus!). Will be fixed in 3.11

     */

#ifdef CONFIG_X86 

    /*

     * If we're the non-boot CPU, nothing set the stack canary up

     * for us. The boot CPU already has it initialized but no harm

     * in doing it again. This is a good place for updating it, as

     * we wont ever return from this function (so the invalid

     * canaries already on the stack wont ever trigger).

     */

    boot_init_stack_canary();
#endif
    arch_cpu_idle_prepare();
    cpuhp_online_idle(state);
    while (1)
        do_idle();
}

猜你喜欢

转载自blog.csdn.net/rikeyone/article/details/84029241