《Linux內核分析》 第八節 進程的切換和通常的執行過程

張嘉琪 原創做品轉載請註明出處 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000算法

Linux內核分析 第八週 進程的切換和通常的執行過程

1、進程切換的關鍵代碼switch_to分析

1.進程進度與進程調度的時機分析

  • 中斷處理過程(包括時鐘中斷、I/O中斷、系統調用和異常)中,直接調用schedule(),或者返回用戶態時根據need_resched標記調用schedule();架構

  • 內核線程能夠直接調用schedule()進行進程切換,也能夠在中斷處理過程當中進行調度,也就是說內核線程做爲一類的特殊的進程能夠主動調度,也能夠被動調度;函數

  • 用戶態進程沒法實現主動調度,僅能經過陷入內核態後的某個時機點進行調度,即在中斷處理過程當中進行調度。post

2.進程上下文切換相關代碼分析

  • 爲了控制進程的執行,內核必須有能力掛起正在CPU上執行的進程,並恢復之前掛起的某個進程的執行,這叫作進程切換、任務切換、上下文切換; 掛起正在CPU上執行的進程,與中斷時保存現場是不一樣的,中斷先後是在同一個進程上下文中,只是由用戶態轉向內核態執行;操作系統

  • 進程上下文包含了進程執行須要的全部信息線程

    • 用戶地址空間:包括程序代碼,數據,用戶堆棧等rest

    • 控制信息:進程描述符,內核堆棧等blog

    • 硬件上下文(注意中斷也要保存硬件上下文只是保存的方法不一樣)進程

  • schedule()函數選擇一個新的進程來運行,並調用contextswitch進行上下文的切換,這個宏調用switchto來進行關鍵上下文切換ip

    • next = picknexttask(rq, prev);//進程調度算法都封裝這個函數內部

    • context_switch(rq, prev, next);//進程上下文切換

    • switch_to利用了prev和next兩個參數:prev指向當前進程,next指向被調度的進程

2、Linux系統的通常執行過程

1.Linux系統的通常執行過程分析

  • 最通常的狀況:正在運行的用戶態進程X切換到運行用戶態進程Y的過程

    1. 正在運行的用戶態進程X
    2. 發生中斷——save cs:eip/esp/eflags(current) to kernel stack,then load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).
    3. SAVE_ALL //保存現場
    4. 中斷處理過程當中或中斷返回前調用了schedule(),其中的switch_to作了關鍵的進程上下文切換
    5. 標號1以後開始運行用戶態進程Y(這裏Y曾經經過以上步驟被切換出去過所以能夠從標號1繼續執行)
    6. restore_all //恢復現場
    7. iret - pop cs:eip/ss:esp/eflags from kernel stack
    8. 繼續運行用戶態進程Y

2.Linux系統執行過程當中的幾個特殊狀況

  • 經過中斷處理過程當中的調度時機,用戶態進程與內核線程之間互相切換和內核線程之間互相切換,與最通常的狀況很是相似,只是內核線程運行過程當中發生中斷沒有進程用戶態和內核態的轉換;

  • 內核線程主動調用schedule(),只有進程上下文的切換,沒有發生中斷上下文的切換,與最通常的狀況略簡略;

  • 建立子進程的系統調用在子進程中的執行起點及返回用戶態,如fork; 加載一個新的可執行程序後返回到用戶態的狀況,如execve;

3.內核與舞女

  • 3G僅內核態能夠訪問

3、Linux系統架構和執行過程概覽

1.Linux操做系統架構概覽

2.最簡單也是最複雜的操做——執行ls操做

3.從CPU和內存的角度看Linux系統的執行

 

 

 

 

4、實驗報告

1、實驗要求

  • 理解Linux系統中進程調度的時機,能夠在內核代碼中搜索schedule()函數,看都是哪裏調用了schedule()

  • 使用gdb跟蹤分析一個schedule()函數 ,驗證您對Linux系統進程調度與進程切換過程的理解;推薦在實驗樓Linux虛擬機環境下完成實驗。 特別關注並仔細分析switch_to中的彙編代碼,理解進程上下文的切換機制,以及與中斷上下文切換的關係;

  • 博客內容中須要仔細分析進程的調度時機、switch_to及對應的堆棧狀態等。

2、實驗步驟

1.打開qemu和gdb

2.設置斷點

3.用list查看代碼

4.單步執行發現__schedule()

5.進入函數

6.繼續單步執行直到發現pick_nexi_task()

7.在pick_next_task處設立斷點,執行

8.在context_switch處設立斷點,執行

 

5、總結

對「Linux系統通常執行過程」的理解


 

    Linux內核中實現進程的切換主要經過保存進程相關的信息實現,這裏須要注意進程切換中內核級進程的切換和用戶態進程切換的不一樣。內核態能夠直接調用schedule函數並不須要陷入中斷這個過程。而用戶態則須要陷入內核態才能實現進程的切換。從switch_to這個函數當中也能夠驗證咱們進程切換時會保存相關信息的推斷。

相關文章
相關標籤/搜索