linux内核的0号进程是在哪里创建的?

1. 0号进程即为idle进程或swapper进程,也就是空闲进程

2. 0号进程特点

  idle是一个进程,其pid为0。

  主处理器上的idle由原始进程(pid=0)演变而来。从处理器上的idle由init进程fork得到,但是它们的pid都为0。

  Idle进程为最低优先级,且不参与调度,只是在运行队列为空的时候才被调度。

  Idle循环等待need_resched置位。默认使用hlt节能。

3. 展示一下源码(linux 5.2)

  void cpu_startup_entry(enum cpuhp_state state)

  {
    arch_cpu_idle_prepare();
    cpuhp_online_idle(state);
    while (1)
      do_idle();
  }

  

 *
 * Called with polling cleared.
 */
static void do_idle(void)
{
        int cpu = smp_processor_id();
        /*
         * If the arch has a polling bit, we maintain an invariant:
         *
         * Our polling bit is clear if we're not scheduled (i.e. if rq->curr !=
         * rq->idle). This means that, if rq->idle has the polling bit set,
         * then setting need_resched is guaranteed to cause the CPU to
         * reschedule.
         */

        __current_set_polling();
        tick_nohz_idle_enter();

        while (!need_resched()) {
                check_pgt_cache();
                rmb();

                if (cpu_is_offline(cpu)) {
                        tick_nohz_idle_stop_tick_protected();
                        cpuhp_report_idle_dead();
                        arch_cpu_idle_dead();
                }

                local_irq_disable();
                arch_cpu_idle_enter();

                /*
                 * In poll mode we reenable interrupts and spin. Also if we
                 * detected in the wakeup from idle path that the tick
                 * broadcast device expired for us, we don't want to go deep
                 * idle as we know that the IPI is going to arrive right away.
                 */
                if (cpu_idle_force_poll || tick_check_broadcast_expired()) {
                       tick_nohz_idle_restart_tick();
                        cpu_idle_poll();
                } else {
                        cpuidle_idle_call();
                }
                arch_cpu_idle_exit();
        }

        /*
         * Since we fell out of the loop above, we know TIF_NEED_RESCHED must
         * be set, propagate it into PREEMPT_NEED_RESCHED.
         *
         * This is required because for polling idle loops we will not have had
         * an IPI to fold the state for us.
         */
        preempt_set_need_resched();
        tick_nohz_idle_exit();
        __current_clr_polling();
        /*
         * We promise to call sched_ttwu_pending() and reschedule if
         * need_resched() is set while polling is set. That means that clearing
         * polling needs to be visible before doing these things.
         */
        smp_mb__after_atomic();

        sched_ttwu_pending();
        schedule_idle();

        if (unlikely(klp_patch_pending(current)))
                klp_update_patch_state(current);
}

  

 

4. 0号进程都干什么了?

  idle进程中并不执行什么有意义的任务,所以通常考虑的是两点:1.节能,2.低退出延迟。 

  循环判断need_resched以降低退出延迟,用idle()来节能。

  默认的idle实现是hlt指令,hlt指令使CPU处于暂停状态,等待硬件中断发生的时候恢复,从而达到节能的目的。即从处理器C0态变到C1态(见 ACPI标准)。这也是早些年windows平台上各种”处理器降温”工具的主要手段。当然idle也可以是在别的ACPI或者APM模块中定义的,甚至是自定义的一个idle(比如说nop)。

 

posted @ 2019-09-20 16:32  Jello  阅读(1051)  评论(0编辑  收藏  举报