官术网_书友最值得收藏!

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”,當然能正常運行。耶!

主站蜘蛛池模板: 彭泽县| 江源县| 乌鲁木齐县| 石门县| 布尔津县| 南漳县| 连云港市| 贵定县| 亚东县| 赤壁市| 崇义县| 托里县| 阜南县| 大厂| 汤原县| 龙川县| 女性| 行唐县| 衡水市| 桐庐县| 宁海县| 清水河县| 佛冈县| 青岛市| 巴彦淖尔市| 云阳县| 驻马店市| 百色市| 东台市| 长乐市| 昌宁县| 通辽市| 花莲县| 阿克陶县| 治县。| 桑日县| 扬中市| 谷城县| 河北区| 老河口市| 江口县|