Linux進程調度和切換過程分析
(1):從schedule()開始,幾種不同類型的進程之間的調度選擇;在相同類型的進程之間的調度選擇算法 (2):從CPU的IP值的變化上,說明在switch_to宏執行後,執行分析 (3):堆棧發生切換位置,在切換堆棧前後,current_thread_info變化 |
1,從schedule()開始,說明幾種不同類型的進程之間的調度選擇;在相同類型的進程之間的調度選擇算法。
在schedule()函數中,
首先禁止搶佔,獲取當前CPU,該CPU的執行隊列,隊列上正在執行的進程,以及該進程的交換計數信息並釋放該進程佔用的鎖。之後,對禁止中斷,更新運行隊列時鐘,該隊列的自旋時鐘加鎖,後清除當前進程的thread_flag中TIF_NEED_RESCHED,
如果進程不在可運行狀態,並且可被搶佔,若進程處於非阻塞掛起,則將其改爲可運行,否則調用deactivate_task()函數,並修改上下文交換次數。其中在deactive_task()函數中調用了denqueue_task()函數:
P進程調用屬於自己調度類的dequeue_task()方法,將p從當前rp運行隊列上移出。例如對於公平調度隊列中的進程調用以下函數:
對p的所有實體除含有子實體的父進程外,從公平隊列中移除。
如果運行隊列上進程數是0,則先通過idle_balance函數從其他CPU上調度,進行負載均衡。
對當前運行的進程prev,通過調用它所屬的類的put_prev_task方法,將當前進程放入運行隊列的合適位置。下圖展示過程,圖爲公平調度類的調度方法,之後對實時調度方法的說明(idle類方法爲空):
與方法put_prev_entity()方法,將當前進程加入公平調度隊列。因爲如果該類是公平調度類,則調度一定會在公平調度隊列中有一位置,更新當前實例的狀態,併入隊:
其中入隊位置有該值決定entity_key:
對於採用實時調度的類,調用update_curr_rt函數,並置當前進程執行開始時間是0
下圖爲update_curr_tr函數,
計算delta_exec值爲運行隊列現在的時鐘值與當前進程開始值。更改當前進程的狀態,修改當前實時進程的總運行時間與開始時間,對實時調度隊列中的實例更新時間。
之後,在運行隊列上選擇下一個進程中pick_next_task函數。
對於運行隊列,如果隊列中進程數與公平調度隊列中的進程數相同,即沒有實時進程時則在公平調度隊列中選擇進程:
對調度類中具有最高優先級的類賦值給class,調用該類的pick_next_task方法,根據不同調度類又分爲:
對於實時進程則:
對於一個實例,如果它不在實時隊列組中,則返回擁有這個實例的task_struct結構爲next進程並修改執行開始時間爲運行隊列當時鐘前值。
對於公平調度進程則:
返回公平調度隊列上選擇不在公平調度組中的task_struct。
對於idle,返回隊列中的idle task_struct結構,在調度過程中,永遠不會返回NULL,因爲至少有idle進程的存在。
在隊列中從不同類中,選擇出了將要被調度的類後,如果選擇的進程next與prev不同則,進行進程的上下文切換:
修改交換次數,將next至爲當前進程,進行切換。
2,執行完switch_to後,又執行了battier函數,之後又執行finish_task_switch函數
另:
struct task_struct *__switch_to(struct task_struct *prev,struct task_struct *next);
將next->thread.esp中的數據存入esp寄存器中
在switch_to宏執行後,執行ret_from_fork()函數。
執行完這個函數之後,執行include/asm-x86/system.h 下的__switch_to函數()
再執行__unlazy_fpu()函數。
3,堆棧發生切換位置,在切換堆棧前後,current_thread_info變化
對於切換堆棧,在switch_to中查找修改堆棧指針代碼即可即:
圖中movel %[next_sp],%%esp 即爲修改堆棧指針,指向next進程的堆棧。因爲在內核態中,棧頂指針減去8K偏移(兩頁)便可得到thread_info位置,從而,在切換後current_thread_info內容爲切換後的新進程的thread_info內容。
4,地址空間發生切換,解釋地址空間的切換不會影響後續切換代碼的執行
切換地址空間在context_switch函數的switch_mm方法,在switch_mm中,重新加載頁表即修改cr3寄存器的值:
切換地址空間發生在切換堆棧之前,不會影響後續代碼執行,因爲進程的切換髮生在內核態,內核態地址空間是共用的。沒有修改堆棧指針及其他寄存器的值,即堆棧沒有變,棧內值未發生改變。
修改該CPU的current_task爲next_p,即current宏發生了改變。
Tss段在_switch_to中被聲明,並被賦值:
其中,esp0即爲內核堆棧棧底指針
</div>
<div class="postDesc">posted @ <span id="post-date">2013-03-05 10:31</span> <a href="http://www.cnblogs.com/sunshinewill/">SONGHY</a> 閱讀(<span id="post_view_count">4637</span>) 評論(<span id="post_comment_count">0</span>) <a href="https://i.cnblogs.com/EditPosts.aspx?postid=2943872" rel="nofollow">編輯</a> <a href="#" onclick="AddToWz(2943872);return false;">收藏</a></div>
</div>
<script type="text/javascript">var allowComments=true,cb_blogId=118555,cb_entryId=2943872,cb_blogApp=currentBlogApp,cb_blogUserGuid='734df011-67a5-e111-aa3f-842b2b196315',cb_entryCreatedDate='2013/3/5 10:31:00';loadViewCount(cb_entryId);</script>
</div><!--end: forFlow -->
</div>
【推薦】羣英雲服務器性價王,2核4G5M BGP帶寬 68元首月!
【福利】阿里雲免費套餐升級,更多產品,更久時長
· 研究顯示:火星土壤可以壓成堅固磚塊用於建造建築物
· 易到司機及用戶採取訴訟維權 海淀法院已立案
· 美國郵政推出熱敏郵票 手指按壓後日全食圖案將變成滿月圖案
· 雲之爭的第二個十年:Azure增速是AWS兩倍,谷歌仍然遮遮掩掩
· ofo小黃車宣佈首位代言人:人氣偶像鹿晗
» 更多新聞…
· 程序員,如何從平庸走向理想?
· 我爲什麼鼓勵工程師寫blog
· 怎麼輕鬆學習JavaScript
· 如何打好前端游擊戰