schedule浪子何時回頭?
刺蝟@http://blog.csdn.net/littlehedgehog
schedule.c 給人最大的疑惑就是一旦把進程調度完成後切換到其他進程時,什麼時候再返回執行呢?
void schedule (void
)
...
{
int
i, next, c;
struct task_struct **
p;
for (p = &LAST_TASK; p > &FIRST_TASK; --
p)
if (*
p)
...
{
if ((*p)->alarm && (*p)->alarm <
jiffies)
...
{
(*p)->signal |= (1 << (SIGALRM - 1
));
(*p)->alarm = 0
;
}
if (((*p)->signal & ~(_BLOCKABLE & (*p)->blocked)) &&
(
*p)->state ==
TASK_INTERRUPTIBLE)
(*p)->state =
TASK_RUNNING;
}
/**//* 這裡是發送器的主要部分 */
while (1
)
...
{
c = -1
;
next = 0
;
i =
NR_TASKS;
p = &
task[NR_TASKS];
while (--
i)
...
{
if (!*--
p)
continue
;
if ((*p)->state == TASK_RUNNING && (*p)->counter >
c)
c = (*p)->counter, next =
i;
}
if
(c)
break
;
for (p = &LAST_TASK; p > &FIRST_TASK; --
p)
if (*
p)
(*p)->counter = ((*p)->counter >> 1) + (*p)->
priority;
}
switch_to (next); //
切換到任務號為next 的任務,並運行之。
}
schedule函數主要是:
1、處理訊號
2、尋找合適發送器
3、切換
我們主要關注在切換這塊。看最後一句,調用switch_to函數,這個函數在shed.h中的171行:
#define switch_to(n) {
struct ...{long a,b;}
__tmp;
__asm__( "cmpl %%ecx,_current "
"je 1f "
"movw %%dx,%1 "
"xchgl %%ecx,_current "
"ljmp %0 "
// 在任務切換回來後才會繼續執行下面的語句。
"cmpl %%ecx,_last_task_used_math "
"jne 1f "
"clts "
"1:"::"m" (*&__tmp.a), "m" (*&
__tmp.b),
"d" (_TSS (n)), "c" ((long
) task[n]));
}
程式運行到 ljmp %0 ,這裡就是ljmp tss ,進行了任務切換,有人也問過為什麼jmp tss 就能進行任務切換呢?
這個是cpu的設計問題了,那要去問intel公司為什麼要這樣設計。不過我們可以設想一下,在tss中所有進程需要的所有內容都有了,包括寄存器、頁目錄表、ldt的選擇符,那麼為什麼不能設計成jmp tss 就可以切換任務呢?如果我是設計人員,我也會這樣設計,方便系統編程人員啊。
jmp tss 後就完成了任務切換。當前任務暫停執行,一直到schedule又重新調度該任務。不過還要補充說明的是: 當前任務進入發送器時,此時已經是核心態了。等我們再回來執行時,同樣是接著在核心態執行。這裡是接著執行 cmpl %%ecx,_last_task_used_math 這條語句,如上面所注釋的一樣。