• xv6的设计trick(不断更新)


    1、每个进程通过时钟中断出发trap.c中的

    if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER)
    yield();来强制把这个进程置为Runnable状态,yield的实现如下:

    acquire(&ptable.lock); //DOC: yieldlock
    proc->state = RUNNABLE;
    sched();
    release(&ptable.lock);

    在sched中

    swtch(&proc->context, cpu->scheduler); 实现从当前进程的kernel Stack 切换到 CPU中专门负责程序调度的 scheduler Stack,

    (gdb) p /x *cpus[0]->scheduler 
    $7 = {edi = 0x0, esi = 0x80104ea4, ebx = 0x8, ebp = 0x8010c608, 
    eip = 0x80104ab2}

    此时,我们在 sched设置断点

    (gdb)b proc.c:314

    (gdb)s  进入汇编代码

    在swtch的汇编代码中,我们将当前进程的esp所指向的内存地址+8 作为新的上下文的esp,然后保存老寄存值,popl加载新的寄存器的值

    swtch:

       movl %esp, (%eax)

       movl %edx, %esp

    edx 的值就是指向 CPU scheduler的栈底指针的值

    2、磁盘文件块读写

    struct buf* bread(uint dev, uint blockno) {
    struct buf* b;
    b = bget(dev, blockno);
    if (!(b.flags & B_VALID)) {
    iderw(b);
    }
    return b;
    }

    static struct buf* bget(uint dev, uint blockno) {
    struct buf* b;
    acquire(&bcache.lk);
    loop:
    for(b = bcache.head.next; b != &bcache.head; b = b->next) {
    //if the buf is already in the buffer
    if (b->dev == dev && b->blockno == blockno) {
    if (!(b.flags & B_BUSY)) {
    b.flags &= B_BUSY;
    release(&bcache.lk);
    return b;
    }
    sleep(b, &bcache.lk);
    goto loop;
    }
    }
    for (b = bcache.head.prev; b != &bcache.head; b = b->next) {
    if((b.flags & B_BUSY) == 0 && (b.flags & B_DIRTY) == 0) {
    b->dev = dev;
    b->blockno = blockno;
    b->flags = B_BUSY;
    release(&bcache.lk);
    return b;
    }
    }
    panic("there isn't any empty buf");
    }

  • 相关阅读:
    2019 滴滴java面试笔试总结 (含面试题解析)
    2019 阿里java面试笔试总结 (含面试题解析)
    Mangos笔记
    Google 多源码管理工具 gclient
    构建系统介绍
    Ninja介绍
    小试 Ninja
    如何使用Ninja快速编译LLVM和Clang
    FMS4中的P2P功能
    Flex之HTML5视频播放解决方案
  • 原文地址:https://www.cnblogs.com/yanchengwang/p/5573857.html
Copyright © 2020-2023  润新知