Linux進程調度和切換過程分析

Linux進程調度和切換過程分析

內容:

(1):從schedule()開始,幾種不同類型的進程之間的調度選擇;在相同類型的進程之間的調度選擇算法

(2):從CPU的IP值的變化上,說明在switch_to宏執行後,執行分析

(3):堆棧發生切換位置,在切換堆棧前後,current_thread_info變化

(4):地址空間發生切換,解釋地址空間的切換不會影響後續切換代碼的執行

(5):current宏所代表的進程發生變化的源碼位置

(6):任務狀態段中關於內核堆棧的信息發生變化源碼位置

 

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寄存器的值:

切換地址空間發生在切換堆棧之前,不會影響後續代碼執行,因爲進程的切換髮生在內核態,內核態地址空間是共用的。沒有修改堆棧指針及其他寄存器的值,即堆棧沒有變,棧內值未發生改變。

5,current宏所代表的進程發生變化的源碼位置

修改該CPU的current_task爲next_p,即current宏發生了改變。

6,任務狀態段中關於內核堆棧的信息發生變化源碼位置

Tss段在_switch_to中被聲明,並被賦值:

其中,esp0即爲內核堆棧棧底指針

標籤: Linux, all
0
0

« 上一篇:Linux內核更新,解決”gzip: stdout: No space left on device”問題
» 下一篇:Google I/O 2013 彩蛋
    </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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章