- 30天自制操作系統(tǒng)
- (日)川合秀實
- 1046字
- 2020-03-11 14:01:52
4 改善FIFO緩沖區(qū)(harib04d)
能不能開發(fā)一個不需要數(shù)據(jù)移送操作的FIFO型緩沖區(qū)呢?答案是可以的。因為我們有個技巧可以用。
這個技巧的基本思路是,不僅要維護下一個要寫入數(shù)據(jù)的位置,還要維護下一個要讀出數(shù)據(jù)的位置。這就好像數(shù)據(jù)讀出位置在追著數(shù)據(jù)寫入位置跑一樣。這樣做就不需要數(shù)據(jù)移送操作了。數(shù)據(jù)讀出位置追上數(shù)據(jù)寫入位置的時候,就相當于緩沖區(qū)為空,沒有數(shù)據(jù)。這種方式很好嘛!

但是這樣的緩沖區(qū)使用了一段時間以后,下一個數(shù)據(jù)寫入位置會變成31,而這時下一個數(shù)據(jù)讀出位置可能已經(jīng)是29或30什么的了。當下一個寫入位置變成32的時候,就走到死胡同了。因為下面沒地方可以寫入數(shù)據(jù)了。

如果當下一個數(shù)據(jù)寫入位置到達緩沖區(qū)終點時,數(shù)據(jù)讀出位置也恰好到達緩沖區(qū)的終點,也就是說緩沖區(qū)正好變空,那還好說。我們只要將下一個數(shù)據(jù)寫入位置和下一個數(shù)據(jù)讀出位置都再置為0就行了,就像轉(zhuǎn)回去從頭再來一樣。
但是總還是會有數(shù)據(jù)讀出位置沒有追上數(shù)據(jù)寫入位置的情況。這時,又不得不進行數(shù)據(jù)移送操作。原來每次都要進行數(shù)據(jù)移送,而現(xiàn)在不用每次都做,當然值得高興,但問題是這樣一來,用戶會說:“有時候操作系統(tǒng)的反應(yīng)不好。這系統(tǒng)不行啊。”嗯,我們還是想盡可能避免所有的數(shù)據(jù)移送操作。
如果將緩沖區(qū)擴展到256字節(jié),的確可以減少移位操作的次數(shù),但是不能從根本上解決問題。
■■■■■
仔細想來,當下一個數(shù)據(jù)寫入位置到達緩沖區(qū)最末尾時,緩沖區(qū)開頭部分應(yīng)該已經(jīng)變空了(如果還沒有變空,說明數(shù)據(jù)讀出跟不上數(shù)據(jù)寫入,只能把部分數(shù)據(jù)扔掉了)。因此如果下一個數(shù)據(jù)寫入位置到了32以后,就強制性地將它設(shè)置為0。這樣一來,下一個數(shù)據(jù)寫入位置就跑到了下一個數(shù)據(jù)讀出位置的后面,讓人覺得怪怪的。但這無關(guān)緊要,沒什么問題。

對下一個數(shù)據(jù)讀出位置也做同樣的處理,一旦到了32以后,就把它設(shè)置為從0開始繼續(xù)讀取數(shù)據(jù)。這樣32字節(jié)的緩沖區(qū)就能一圈一圈地不停循環(huán),長久使用。數(shù)據(jù)移送操作一次都不需要。打個比方,這就好像打開一張世界地圖,一直向右走的話,會在環(huán)繞地球一周后,又從左邊出來。這樣一來,這個緩沖區(qū)雖然只有32字節(jié),可只要不溢出的話,它就能夠持續(xù)使用下去。
■■■■■
如果不是很理解以上說明的話,可以看看程序,一看就能會明白。
bootpack.h節(jié)選
struct KEYBUF { unsigned char data[32]; int next_r, next_w, len; };
變量len是指緩沖區(qū)能記錄多少字節(jié)的數(shù)據(jù)。
int.c節(jié)選
void inthandler21(int *esp) { unsigned char data; io_out8(PIC0_OCW2, 0x61); /* 通知IRQ-01已經(jīng)受理完畢 */ data = io_in8(PORT_KEYDAT); if (keybuf.len < 32) { keybuf.data[keybuf.next_w] = data; keybuf.len++; keybuf.next_w++; if (keybuf.next_w == 32) { keybuf.next_w = 0; } } return; }
以上無非是將我們的說明寫成了程序而已,并沒什么難點。倒不如這樣說,正是因為看了以上程序,大家才能搞清楚筆者想要說什么。讀出數(shù)據(jù)的程序如下:
for (; ; ) { io_cli(); if (keybuf.len == 0) { io_stihlt(); } else { i = keybuf.data[keybuf.next_r]; keybuf.len——; keybuf.next_r++; if (keybuf.next_r == 32) { keybuf.next_r = 0; } io_sti(); sprintf(s, "%02X", i); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s); } }
看吧,沒有任何數(shù)據(jù)移送操作。這個緩沖區(qū)可以記錄大量數(shù)據(jù),執(zhí)行速度又快,真是太棒啦。我們測試一下,運行“make run”,當然能正常運行。耶!
- 全屋互聯(lián):智能家居系統(tǒng)開發(fā)指南
- Kubernetes修煉手冊
- 每天5分鐘玩轉(zhuǎn)Kubernetes
- 發(fā)布!設(shè)計與部署穩(wěn)定的分布式系統(tǒng)(第2版)
- Linux實戰(zhàn)
- 計算機系統(tǒng)開發(fā)與優(yōu)化實戰(zhàn)
- 新手學電腦從入門到精通(Windows 10+Office 2016版)
- STM32庫開發(fā)實戰(zhàn)指南:基于STM32F4
- 嵌入式實時操作系統(tǒng):RT-Thread設(shè)計與實現(xiàn)
- Android物聯(lián)網(wǎng)開發(fā)細致入門與最佳實踐
- Linux服務(wù)器配置與管理
- Python UNIX和Linux系統(tǒng)管理指南
- μC/OS-III內(nèi)核實現(xiàn)與應(yīng)用開發(fā)實戰(zhàn)指南:基于STM32
- 鴻蒙入門:HarmonyOS應(yīng)用開發(fā)
- Linux指令從初學到精通