xv6/调度算法及并发程序设计
?
1 在proc.c的scheduler函數中,有兩行:
?if(setjmp(&cpus[cpu()].jmpbuf) == 0)
?longjmp(&p->jmpbuf);
?把它修改為:?
cprintf("setjmp called in scheduler\n");
if(setjmp(&cpus[cpu()].jmpbuf) == 0){
?cprintf("setjmp in scheduler returned 0; longjmp\n");
?longjmp(&p->jmpbuf);
?}else
?cprintf("setjmp in scheduler returned 1\n");
?
修改后,重編譯內核,在Bochs中運行編譯后的內核,你將會看到有規律的六行輸出在屏幕上。
?要求:
?
?
?? int? setjmp(struct jmpbuf *jmp);
?? void longjmp(struct jmpbuf *jmp); 的函數解析!
?
# Setjmp saves its stack environment in jmp for later use by longjmp.
# It returns 0.
?
# Longjmp restores the environment saved by the last call of setjmp.
# It then causes execution to continue as if the call of setjmp
# had just returned 1.
?
# The caller of setjmp must not itself have returned in the interim.
# All accessible data have values as of the time longjmp was called.
?
# [Description, but not code, borrowed from Plan 9.]
?
? 這是setjmp和longjmp的函數解析。意思在于setjmp會保存當前環境,上下文。然后longjmp會回溯到最后一個setjmp所指向保存的環境。如圖1所示
?
???????????????????????????? 圖1
cprintf("setjmp called in scheduler\n");
if(setjmp(&cpus[cpu()].jmpbuf) == 0){
?cprintf("setjmp in scheduler returned 0; longjmp\n");
?longjmp(&p->jmpbuf); ?
?}else
?cprintf("setjmp in scheduler returned 1\n");
?
一開始的時候沒有longjmp的時候,setjmp返回的為0.
然后執行cprintf("setjmp in scheduler returned 0; longjmp\n");
接著到longjmp 于是跳回setjmp的位置。此時因為longjmp了于是setjpm返回1。
于是執行cprintf("setjmp in scheduler returned 1\n");
所以才有一次setjmp returned 才輸出一行setjmp called。
?
?
?
?
?
可以從scheduler函數和sched函數的注釋中看出.
對于scheduler函數
// Per-CPU process scheduler.
// Each CPU calls scheduler() after setting itself up.
// Scheduler never returns.? It loops, doing:
//? - choose a process to run
//? - longjmp to start running that process
//? - eventually that process transfers control back
//??? via longjmp back to the top of scheduler.
每一個CPU都有屬于它自己的scheduler函數,當每一個CPU設置它本身的時候會調用scheduler函數的時候。Scheduler函數永遠不會返回,它會不斷的循環:(循環過程中)
?? 1 選擇一個進程,然后運行該進程。
?? 2 使用longjmp跳到那個進程代碼那,開始運行那個進程。
?? 3 最后進程將控制權轉移回來。
?? 4 通過longjmp調到scheduler函數頭。重新開始。
?
對于 sched函數
// Enter scheduler.? Must already hold proc_table_lock
// and have changed curproc[cpu()]->state.
在進入scheduler 函數,而且會在持有 proc_table_lock
并且會改變 curproc[cpu()]的狀態。
?
?
?
?
?
?
?
4. 閱讀trap.c 第50行至第66行。Proc.c中的 yield函數、sched函數及scheduler函數,結合書本,確定xv6使用的是哪種調度算法。給出你的理由(通過分析代碼證明你的觀點)。
?
1先來先服務(FCFS)
2短作業優先(SF)
3高響應比優先
4時間片輪轉(RR)
5多級隊列調度算法
6多級反饋隊列調度算法總共有6調度算法是XV6可能的選項。
前三種都是要安裝進程的某個屬性排序,比如進入時間,比如作業長短,響應比。并且選擇進入時間最早,作業最短,響應比最高。
Scheduler 函數中的
for(i = 0; i < NPROC; i++){
????? p = &proc[i];
????? if(p->state != RUNNABLE)
??????? continue;
?
這部分是調度算法的核心,證明了XV6是使用時間輪轉(RR)。因為上面代碼就是一個循環,在process數組里尋找可執行的進程。然后接下去的代碼的意義才是跳到被選中的進程去進行執行。
// Switch to chosen process.? It is the process's job
// to release proc_table_lock and then reacquire it
// before jumping back to us.
?
????? setupsegs(p);
????? curproc[cpu()] = p;
????? p->state = RUNNING;
????? if(setjmp(&cpus[cpu()].jmpbuf) == 0)
??????? longjmp(&p->jmpbuf);
?
至于yield 函數 sched函數。當一個進程使用完時間片后,會中斷調用yield函數來讓出CPU給新的進程,yield調用sched函數,sched會切換:
void
sched(void)
{
? struct proc *p = curproc[cpu()];
?
? if(!holding(&proc_table_lock))
??? panic("sched");
? if(cpus[cpu()].nlock != 1)
??? panic("sched locks");
?
? if(setjmp(&p->jmpbuf) == 0)
??? longjmp(&cpus[cpu()].jmpbuf);
}
?
轉載于:https://www.cnblogs.com/zzzPark/p/6865625.html
總結
以上是生活随笔為你收集整理的xv6/调度算法及并发程序设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: clientWidth、clientHe
- 下一篇: 《Redis开发与运维》读书笔记三