1. 程式人生 > >30天自制作業系統之第15天 多工(1)

30天自制作業系統之第15天 多工(1)

多工的本質是利用定時器和far跳轉在任務之間進行切換,具體來說,一開始先執行main函式(就是處理我們的滑鼠、鍵盤和定時器等事件),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切換一次任務的簡單多工功能。