第八週 進程的切換和系統的通常執行過程

第八週 進程的切換和系統的通常執行過程

【黎靜 原創做品轉載請註明出處 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000】web

1、進程切換關鍵代碼switch_to

1.不一樣類型進程有不一樣調度需求——兩種分類算法

進程分類

分類1shell

  1. I/O-bound:等待I/O架構

  2. CPU-bound:大量佔用CPU進行計算函數

分類2spa

  1. 交互式進程(shell)線程

  2. 實時進程rest

  3. 批處理進程blog

進程調度策略

  • 一組決定什麼時候以何種方式選擇進程的規則隊列

  • Linux的調度基於分時和優先級策略:

    • 進程根據優先級(系統根據特定算法計算出來)排隊;

    • 這個優先級的值表示如何適當分配CPU;

    • 調度程序會根據進程的運行週期動態調整優先級;

    • 好比nice等系統調用,能夠手動調整優先級

  • 調度策略本質上是一種算法,這些算法從實現的角度看僅僅是從運行隊列中選擇一個新進程,選擇的過程當中運用了不一樣的策略而已

  • 內核中的調度算法相關代碼使用了相似OOD中的策略模式

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

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

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

  • 硬件上下文(與中斷保存硬件上下文的方法不一樣)

代碼

  • switch_to完成寄存器的切換:先保存當前進程的寄存器,再進行堆棧切換(下圖第4四、45行)自此後全部的壓棧都是在新進程的堆棧中了,再切換eip,這樣當前進程能夠重新進程中恢復,還有其餘必要的切換
  • next_ip通常是$1f(對於新建立的進程來講就是ret_from_fork)
  • jmp __switch_to是函數調用,經過寄存器傳遞參數;函數執行結束return的時候從下一條指令開始(也就是認爲是新進程的開始)

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

1.從正在運行的用戶態進程X到Y

X正在運行--->發生中斷,可能陷入內核,CPU自動保存加載--->SAVE_ALL保存現場--->調用scheduleswitch_to進程上下文切換--->標號1以後運行Y(以前有進行準備動做)--->restore_all恢復現場--->iret- pop cs:eip/ss:esp/eflags from kernel stack--->繼續運行用戶態進程Y

2.特殊狀況

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

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

建立子進程的系統調用在子進程中的執行起點及返回用戶態,如fork

加載一個新的可執行程序後返回到用戶態的狀況,如execve

  • 內核地址空間的4G3G以上是內核態能夠訪問的——是全部進程共享的。
  • 涉及中斷、終端控制檯設備驅動的概念。

3.內核——Taxi

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

1.執行ls命令

過程:

shell分析-->調用系統調用fork生成一個shell自己拷貝-->調用exec系統調用將ls可執行文件裝入內存-->從系統調用返回

4、實踐

schedule()函數選擇一個新的進程來運行,並調用context_switch進行上下文的切換,context_switch是一個宏,這個宏調用switch_to()函數來進行關鍵上下文切換
next = pick_next_task(rq, prev); //進程調度算法都封裝這個函數內部
context_switch(rq, prev, next); //進程上下文切換
switch_to利用了prevnext兩個參數:prev指向當前進程,next指向被調度的進程

 



  1. 在schedule處設置斷點,點擊c運行。【能夠看到此時被凍結的內核開始運行直到schedule處】
  2. list查看斷點所在代碼段。能夠與上圖對照,發現第2804行即schedule()函數
  3. c以後按n單步執行,直到遇到__schedule函數,進入其中查看
  4. 繼續執行,直到發現context_switch函數
  5. 設置斷點後,設法進入其內部查看
相關文章
相關標籤/搜索