微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

处理用户空间中的磁盘中断MIT 6.828 JOS实验5

如何解决处理用户空间中的磁盘中断MIT 6.828 JOS实验5

我将尝试使这个问题尽可能地笼统。背景是我现在正在尝试6.828 LAB 5挑战。

挑战!实施带或不带DMA的中断驱动的IDE磁盘访问。您可以决定是将设备驱动程序移入内核,还是将其与文件系统一起保留在用户空间中,或者(如果您真的想融入微内核的精神)将其移至自己的单独环境中。

我试图将驱动程序保留在用户空间中,但是我发现有关计时器中断的问题,请参见下面粘贴的代码,这是我在注释中加上的原因:

int
ide_read(uint32_t secno,void *dst,size_t nsecs)
{
    int r;

    assert(nsecs <= 256);

    ide_wait_ready(0);

    outb(0x1F2,nsecs);
    outb(0x1F3,secno & 0xFF);
    outb(0x1F4,(secno >> 8) & 0xFF);
    outb(0x1F5,(secno >> 16) & 0xFF);
    outb(0x1F6,0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));

    // between issuing disk cmd and set to sleep,there might be a timer IRQ
    // comes in,and fs -> RUNNABLE,then disk IRQ comes,and we handle it
    // then fs goes to sleep,with cpu halted,we missed wake up
    sys_ide_sleep(dst,nsecs,0);

    return 0;
}

sys_ide_sleep系统调用如下:

static void
sys_ide_sleep(void *chan,size_t nsecs,int op)
{
    int r;
    if (op == 0)
    {
        outb(0x1F7,nsecs > 1 ? 0xc4 : 0x20);   // CMD 0x20 means read sector
    }
    else
    {
        outb(0x1F7,nsecs > 1 ? 0xc5 : 0x30);   // CMD 0x30 means write sector
        outsl(0x1F0,chan,PGSIZE / 4);
    }
    curenv->chan = chan;
    curenv->env_status = ENV_IDE_SLEEPING;
    curenv->op = op;
    sched_yield();
}

我想到了在系统调用中传递一个共享的布尔变量的地址,一旦IRQ被确认并处理,我们就设置is_finished = true。所以我想出了sys_ide_sleep(&is_finished),在我们决定使用sched_yield()产生cpu之前,我们可以像这样进行检查:

if (*is_finished == false)
{
    sched_yield();
}

但是我不知道是否有任何更优雅或更好的方法可以做到这一点(我不认为以这种方式与内核共享内存是好方法),任何评论或回答都将不胜感激。谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。