30天自制作業系統之第15天 多工(1)
阿新 • • 發佈:2019-01-31
多工的本質是利用定時器和far跳轉在任務之間進行切換,具體來說,一開始先執行main函式(就是處理我們的滑鼠、鍵盤和定時器等事件),0.02s後定時器超時,執行如下語句:
far-JMP指令指向的目標地址段是4*8,這是任務B的TSS所在,因此實際上是發生了任務切換,下面是任務B的TSS設定:
之後任務B得到執行,下面是任務B的函式:
在任務B中我們同樣設定了超時時間為0.02s的定時器,也就是說在任務B執行0.02s後,又任務切換到了A,即上面的main函式中。切換到任務A,緊接著繼續設定0.02s的定時器,這樣反覆進行下去,就出現了每0.02s切換一次任務的簡單多工功能。
farjmp(0, 4 * 8);
這是一個far跳轉,先看一下farjmp的實現:
_farjmp: ; void farjmp(int eip, int cs)
JMP FAR [ESP+4] ; eip, cs
RET
far-JMP指令指向的目標地址段是4*8,這是任務B的TSS所在,因此實際上是發生了任務切換,下面是任務B的TSS設定:
set_segmdesc(gdt + 4, 103, (int) &tss_b, AR_TSS32);
之後任務B得到執行,下面是任務B的函式:
void task_b_main(struct SHEET *sht_back) { //for (;;) { io_hlt(); } struct FIFO32 fifo; struct TIMER *timer_ts, *timer_put; int i, fifobuf[128], count = 0; char s[11]; fifo32_init(&fifo, 128, fifobuf); timer_ts = timer_alloc(); timer_init(timer_ts, &fifo, 2); timer_settime(timer_ts, 2); timer_put = timer_alloc(); timer_init(timer_put, &fifo, 1); timer_settime(timer_put, 1); for (;;) { count++; io_cli(); if (fifo32_status(&fifo) == 0) { //io_stihlt(); io_sti(); } else { i = fifo32_get(&fifo); io_sti(); if (i == 1) { // each 0.01s refreshing the screen, not each count++, enhancing the performance sprintf(s, "%11d", count); putfonts8_asc_sht(sht_back, 0, 144, COL8_FFFFFF, COL8_0000FF, s, 11); timer_settime(timer_put, 1); } else if (i == 2) { farjmp(0, 3 * 8); timer_settime(timer_ts, 2); } } } }
在任務B中我們同樣設定了超時時間為0.02s的定時器,也就是說在任務B執行0.02s後,又任務切換到了A,即上面的main函式中。切換到任務A,緊接著繼續設定0.02s的定時器,這樣反覆進行下去,就出現了每0.02s切換一次任務的簡單多工功能。