idel進程


1. idle是什么   
  簡單的說idle是一個進程,其pid號為 0。其前身是系統創建的第一個進程,也是唯一一個沒有通過fork()產生的進程。在smp系統中,每個處理器單元有獨立的一個運行隊列,而每個運行隊
列上又有一個idle進程,即有多少處理器單元,就有多少idle進程。系統的空閑時間,其實就是指idle進程的"運行時間"。既然是idle是進程,那我們來看看idle是如何被創建,又具體做了哪
些事情?  
2. idle的創建   
  我們知道系統是從BIOS加電自檢,載入MBR中的引導程序(LILO/GRUB),再加載linux內核開始運行的,一直到指定shell開始運行告一段落,這時用戶開始操作Linux。而大致是在vmlinux
的入口startup_32(head.S)中為pid號為0的原始進程設置了執行環境,然后原是進程開始執行start_kernel()完成Linux內核的初始化工作。包括初始化頁表,初始化中斷向量表,初始化系
統時間等。繼而調用 fork(),創建第一個用戶進程:   
            kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);   
這個進程就是着名的pid為1的init進程,它會繼續完成剩下的初始化工作,然后execve(/sbin/init), 成為系統中的其他所有進程的祖先。關於init我們這次先不研究,回過頭來看pid=0
的進程,在創建了init進程后,pid=0的進程調用 cpu_idle()演變成了idle進程。   
                    current_thread_info()->status |= TS_POLLING;   
在 smp系統中,除了上面剛才我們講的主處理器(執行初始化工作的處理器)上idle進程的創建,還有從處理器(被主處理器activate的處理器)上的 idle進程,他們又是怎么創建的呢?接着
看init進程,init在演變成/sbin/init之前,會執行一部分初始化工作,其中一個就是 smp_prepare_cpus(),初始化SMP處理器,在這過程中會在處理每個從處理器時調用   
            task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);   
            init_idle(task, cpu);   
即從init中復制出一個進程,並把它初始化為idle進程(pid仍然為0)。從處理器上的idle進程會進行一些Activate工作,然后執行cpu_idle()。   
    整個過程簡單的說就是,原始進程(pid=0)創建init進程(pid=1),然后演化成idle進程(pid=0)。init進程為每個從處理器(運行隊列)創建出一個idle進程(pid=0),然后演化成
/sbin/init。   
  3. idle的運行時機   
    idle 進程優先級為MAX_PRIO,即最低優先級。早先版本中,idle是參與調度的,所以將其優先級設為最低,當沒有其他進程可以運行時,才會調度執行 idle。而目前的版本中
idle並不在運行隊列中參與調度,而是在運行隊列結構中含idle指針,指向idle進程,在調度器發現運行隊列為空的時候運行,調入運行。   
  4. idle的workload   
    從上面的分析我們可以看出,idle在系統沒有其他就緒的進程可執行的時候才會被調度。不管是主處理器,還是從處理器,最后都是執行的cpu_idle()函數。所以我們來看看
cpu_idle做了什么事情。   
    因為idle進程中並不執行什么有意義的任務,所以通常考慮的是兩點:1.節能,2.低退出延遲。   
    其核心代碼如下:   
      void cpu_idle(void) 
      { 
        int cpu = smp_processor_id(); 
        current_thread_info()->status |= TS_POLLING; 
        while (1) 
        { 
          tick_nohz_stop_sched_tick(1);
           while (!need_resched()) 
          { 
            check_pgt_cache(); 
            rmb();
            if (rcu_pending(cpu)) 
              rcu_check_callbacks(cpu, 0); 
            if (cpu_is_offline(cpu)) 
              play_dead(); 
            local_irq_disable();
             __get_cpu_var(irq_stat).idle_timestamp = jiffies; 
            stop_critical_timings(); 
            pm_idle(); 
            start_critical_timings(); 
          } 
          tick_nohz_restart_sched_tick(); 
          preempt_enable_no_resched(); 
          schedule(); 
          preempt_disable(); 
        } 
      }   
    循環判斷need_resched以降低退出延遲,用idle()來節能。   
    默認的idle實現是hlt指令,hlt指令使CPU處於暫停狀態,等待硬件中斷發生的時候恢復,從而達到節能的目的。即從處理器C0態變到 C1態(見 ACPI標准)。這也是早些年
windows平台上各種"處理器降溫"工具的主要手段。當然idle也可以是在別的ACPI或者APM模塊中定義的,甚至是自定義的一個idle(比如說nop)。   
    小結:   
      1.idle是一個進程,其pid為0。   
      2.主處理器上的idle由原始進程(pid=0)演變而來。從處理器上的idle由init進程fork得到,但是它們的pid都為0。   
      3.Idle進程為最低優先級,且不參與調度,只是在運行隊列為空的時候才被調度。   
      4.Idle循環等待need_resched置位。默認使用hlt節能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM