30天自制操作系统
上QQ阅读APP看书,第一时间看更新

4 改善FIFO缓冲区(harib04d)

能不能开发一个不需要数据移送操作的FIFO型缓冲区呢?答案是可以的。因为我们有个技巧可以用。

这个技巧的基本思路是,不仅要维护下一个要写入数据的位置,还要维护下一个要读出数据的位置。这就好像数据读出位置在追着数据写入位置跑一样。这样做就不需要数据移送操作了。数据读出位置追上数据写入位置的时候,就相当于缓冲区为空,没有数据。这种方式很好嘛!

但是这样的缓冲区使用了一段时间以后,下一个数据写入位置会变成31,而这时下一个数据读出位置可能已经是29或30什么的了。当下一个写入位置变成32的时候,就走到死胡同了。因为下面没地方可以写入数据了。

如果当下一个数据写入位置到达缓冲区终点时,数据读出位置也恰好到达缓冲区的终点,也就是说缓冲区正好变空,那还好说。我们只要将下一个数据写入位置和下一个数据读出位置都再置为0就行了,就像转回去从头再来一样。

但是总还是会有数据读出位置没有追上数据写入位置的情况。这时,又不得不进行数据移送操作。原来每次都要进行数据移送,而现在不用每次都做,当然值得高兴,但问题是这样一来,用户会说:“有时候操作系统的反应不好。这系统不行啊。”嗯,我们还是想尽可能避免所有的数据移送操作。

如果将缓冲区扩展到256字节,的确可以减少移位操作的次数,但是不能从根本上解决问题。

■■■■■

仔细想来,当下一个数据写入位置到达缓冲区最末尾时,缓冲区开头部分应该已经变空了(如果还没有变空,说明数据读出跟不上数据写入,只能把部分数据扔掉了)。因此如果下一个数据写入位置到了32以后,就强制性地将它设置为0。这样一来,下一个数据写入位置就跑到了下一个数据读出位置的后面,让人觉得怪怪的。但这无关紧要,没什么问题。

对下一个数据读出位置也做同样的处理,一旦到了32以后,就把它设置为从0开始继续读取数据。这样32字节的缓冲区就能一圈一圈地不停循环,长久使用。数据移送操作一次都不需要。打个比方,这就好像打开一张世界地图,一直向右走的话,会在环绕地球一周后,又从左边出来。这样一来,这个缓冲区虽然只有32字节,可只要不溢出的话,它就能够持续使用下去。

■■■■■

如果不是很理解以上说明的话,可以看看程序,一看就能会明白。

bootpack.h节选

struct KEYBUF {
    unsigned char data[32];
    int next_r, next_w, len;
};

变量len是指缓冲区能记录多少字节的数据。

int.c节选

void inthandler21(int *esp)
{
    unsigned char data;
    io_out8(PIC0_OCW2, 0x61); /* 通知IRQ-01已经受理完毕 */
    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;
}

以上无非是将我们的说明写成了程序而已,并没什么难点。倒不如这样说,正是因为看了以上程序,大家才能搞清楚笔者想要说什么。读出数据的程序如下:

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);
    }
}

看吧,没有任何数据移送操作。这个缓冲区可以记录大量数据,执行速度又快,真是太棒啦。我们测试一下,运行“make run”,当然能正常运行。耶!