進程上下文切換分析


我今天分析一下進程的上下文切換,也就是進程調度時,怎么由當前進程切換到另一個進程的。

1、概述

  進程調度的時機,也就是進程是在啥時候切換,觸發因數是什么。

  中斷發生時,進入中斷處理中斷服務程序——比如我們前面講的系統調用,會直接調用schedule(),或者返回用戶態時根據need_resched標志調用schedule

  內核線程可以直接調用schedule(),從而主動調度。

       用戶態進程無法調用到內存函數schedule,所以他是無法進行主動調度的,他只能由於某些原因導致陷入內核態時才會被調度——比如中斷。

2、進程調度schedule()函數的跟蹤

 如上圖,schedule——>__schedule——>pick_next_task().,pick_next_task這個函數封裝了進程調度算法,他返回下一個需要調度的進程。

當找到需要調度的函數后,通過調用 context_switch——>switch_to進行切換。下面我們看下switch_to這個匯編宏

asm volatile("pushfl\n\t" /* save flags */ \
"pushl %%ebp\n\t" /* save EBP */ \ 
"movl %%esp,%[prev_sp]\n\t" /* save ESP */ \         ——到這里將堆棧老進程堆棧保存起來了
"movl %[next_sp],%%esp\n\t" /* restore ESP */ \      ——切換到新進程堆棧
"movl $1f,%[prev_ip]\n\t" /* save EIP */ \
"pushl %[next_ip]\n\t" /* restore EIP */ \                    ——准備eip
__switch_canary \
"jmp __switch_to\n" /* regparm call */ \                   ——新進程的eip 寫入eip寄存器,下面就正式切換到新進程了 ,這個為啥jmp __switch_to,不用call?
"1:\t" \
"popl %%ebp\n\t" /* restore EBP */ \
"popfl\n" /* restore flags */ \
\
/* output parameters */ \
: [prev_sp] "=m" (prev->thread.sp), \
[prev_ip] "=m" (prev->thread.ip), \
"=a" (last), \
\
/* clobbered output registers: */ \
"=b" (ebx), "=c" (ecx), "=d" (edx), \
"=S" (esi), "=D" (edi) \
\
__switch_canary_oparam \
\
/* input parameters: */ \
: [next_sp] "m" (next->thread.sp), \
[next_ip] "m" (next->thread.ip), \
\
/* regparm parameters for __switch_to(): */ \
[prev] "a" (prev), \
[next] "d" (next) \
\
__switch_canary_iparam \
\
: /* reloaded segment registers */ \
"memory"); \
} while (0)

3、jmp __switch_to 

  jmp是不會講下一條指令push到堆棧中的,這樣的話他返回時就返回的是nexp_ip。 如果用call,就會將下一條指令1: 壓棧,這樣返回時就一定會返回到這里。

  如果新的進程是剛創建的,他的next_ip不是1:, 而是 ret_from_fork,那么如果用call不就有問題了


免責聲明!

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



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