[linux]進程(三)——idle進程


9,linux進程切換

進程切換:
基本概念:
進程上下文:當一個進程在執行時,CPU的所有寄存器中的值、進程的狀態以及堆棧中的內容被稱為該進程的上下文。當內核需要切換到另一個進程時,它需要保存當前進程的所有狀態,即保存當前進程的上下文,運行於進程上下文的進程是可以被搶占的。
硬件上下文:進程恢復執行前必須載入寄存器的一組數據稱為硬件上下文
linux內核在進程切換的時候是並不區分進程和線程的~因為切換是針對task,
進程切換的時機:一般是在系統調用或者中斷的時候,發生在內核態。
進程切換過程:
進程切換統一發生在schedule()函數中,核心函數是context_switch()函數,代碼位置:kernel/kernel/sched/Core.c文件,以ARM為基礎講解linux進程的切換:linux進程切換過程,schedule()函數代碼分析:schedule()代碼分析 schedule代碼分析二

 

10,idle進程

idle進程的概念:
簡單的說idle是一個進程,其pid號為 0。其前身是系統創建的第一個進程,也是唯一一個沒有通過fork()產生的進程。在smp系統中,每個處理器單元有獨立的一個運行隊列,而每個運行隊列上又有一個idle進程,即有多少處理器單元,就有多少idle進程。系統的空閑時間,其實就是指idle進程的"運行時間"。idle進程pid==o,也就是init_task.


idle進程的創建:
vmlinux的入口是arch/arm/kernel/head.S,(關注ENTRY(stext)的位置)入口地址可以從kernel/arch/arm/kernel/vmlinux.lds.S得知文件,在該匯編文件中為pid為0的原始進程設置了執行環境,包括先禁止MMU,內核剛開始是用物理地址的,禁止I-Cache和D-Cache,然后讀取RO,R1,R2,然后原是進程開始執行start_kernel()完成Linux內核的初始化工作。包括初始化頁表,初始化中斷向量表,初始化系統時間等。繼而調用 fork(),創建第一個用戶進程: 創建init進程(pid==1)的函數如下:
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
pid為1的init進程,它會繼續完成剩下的初始化工作,然后execve(/sbin/init), 成為系統中的其他所有進程的祖先,pid為0的idle進程在創建了init進程后,pid=0的進程調用 cpu_idle()演變成了idle進程。current_thread_info()->status |= TS_POLLING;init在演變成/sbin/init之前,會執行一部分初始化工作,其中一個就是 smp_prepare_cpus(),初始化SMP處理器,在這過程中會在處理每個從處理器時調用 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0); init_idle(task, cpu);
 
idle進程的運行時機:
idle進程優先級為MAX_PRIO,即最低優先級。早先版本中,idle是參與調度的,所以將其優先級設為最低,當沒有其他進程可以運行時,才會調度執行idle,而目前的版本中idle並不在運行隊列中參與調度,而是在運行隊列結構中含idle指針,指向idle進程,在調度器發現運行隊列為空的時候運行,調入運行  


idle進程到底做了什么:
idle進程最終調用了cpu_idle()函數

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到我的代碼片
 
  1. process.c  
  2. void cpu_idle(void)  
  3. {  
  4.     ......  
  5.     /* endless idle loop with no priority at all */  
  6.     while (1) {  
  7.         ......  
  8.         while (!need_resched()) {  
  9.             if (cpu_is_offline(smp_processor_id())) {  
  10.                 tick_set_cpu_plugoff_flag(1);  
  11.                 cpu_die(); /* plugoff CPU */  
  12.             }  
  13.             ......  
  14.             if (cpuidle_idle_call())  
  15.                 pm_idle(); /* 進入低電 */  
  16.         }  
  17.         ......  
  18.         schedule_preempt_disabled(); /* 調用schedule() */  
  19.     }  
  20. }  

 

 

補充:linux kernel的啟動流程
當嵌入式設備從uboot跳轉到kernel的時候,首先運行的是kernel的自解壓程序,linux內核在編譯后是以壓縮文件形式存在,路徑是kernel/out/arch/arm/boot/zImage
zImage里的代碼和數據是如何存放的,答:根據out/arch/arm/boot/compressed/vmlinux.lds文件,如果要修改代碼段和數據段位置也需要修改該鏈接腳本。
kernel init的基本流程如下:
     .stext 
      start_kernel() 
      rest_init() 
      kernel_init() 


免責聲明!

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



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