Lab 5: File system, Spawn and Shell
lab 5 如果实验者仅仅按照code 提示去补全代码把实验搞定,就会觉得明显这里比前面几个实验要水.
但是!如果自己有兴趣去深究的话,就会觉得很值得的.不要仅仅满足于代码补全填空.你都走到这一步了.何不多花些时间尽量的多学习一点FS捏?
玩到lab5的话,希望可以一起交流讨论 touch me by e-mail: [email protected]
Disk Access
The x86 processor uses the IOPL bits in the EFLAGS register to determine whether protected-mode code is allowed to perform special device I/O instructions such as the IN and OUT instructions. Since all of the IDE disk
registers we need to access are located in the x86‘s I/O space rather than being memory-mapped, giving "I/O privilege" to the file system environment is the only thing we need to do in order to allow the file system to access these registers. In effect, the
IOPL bits in the EFLAGS register provides the kernel with a simple "all-or-nothing" method of controlling whether user-mode code can access I/O space.
在 kern/env.c里面补全下面的代码即可
The Block Cache
In our file system, we will implement a simple "buffer cache" (really just a block cache) with the help of
the processor‘s virtual memory system. The code for the block cache is in fs/bc.c
static void bc_pgfault(struct UTrapframe *utf) { void *addr = (void *) utf->utf_fault_va; uint32_t blockno = ((uint32_t)addr - DISKMAP) / BLKSIZE; int r; // Check that the fault was within the block cache region if (addr < (void*)DISKMAP || addr >= (void*)(DISKMAP + DISKSIZE)) panic("page fault in FS: eip %08x, va %08x, err %04x", utf->utf_eip, addr, utf->utf_err); // Sanity check the block number. if (super && blockno >= super->s_nblocks) panic("reading non-existent block %08x\n", blockno); // Allocate a page in the disk map region, read the contents // of the block from the disk into that page. // Hint: first round addr to page boundary. fs/ide.c has code to read // the disk. // // LAB 5: you code here: envid_t envid = thisenv->env_id; void *blkaddr = ROUNDDOWN(addr, PGSIZE); if (sys_page_alloc(envid, blkaddr, PTE_SYSCALL) < 0) { panic("bg_pgfault:can't allocate new page for disk block\n"); } if (ide_read(blockno * BLKSECTS, blkaddr, BLKSECTS) < 0) { panic("bg_pgfault: failed to read disk block\n"); } if (sys_page_map(envid, blkaddr, envid, blkaddr, PTE_SYSCALL) < 0) { panic("bg_pgfault: failed to mark disk page as non dirth\n"); } // Clear the dirty bit for the disk block page since we just read the // block from disk if ((r = sys_page_map(0, addr, 0, addr, uvpt[PGNUM(addr)] & PTE_SYSCALL)) < 0) panic("in bc_pgfault, sys_page_map: %e", r); // Check that the block we read was allocated. (exercise for // the reader: why do we do this *after* reading the block // in?) if (bitmap && block_is_free(blockno)) panic("reading free block %08x\n", blockno); }
// Write req->req_n bytes from req->req_buf to req_fileid, starting at // the current seek position, and update the seek position // accordingly. Extend the file if necessary. Returns the number of // bytes written, or < 0 on error. int serve_write(envid_t envid, struct Fsreq_write *req) { if (debug) cprintf("serve_write %08x %08x %08x\n", envid, req->req_fileid, req->req_n); // LAB 5: Your code here. int r = 0; struct OpenFile *o = NULL; size_t nbytes = 0; r = openfile_lookup(envid, req->req_fileid, &o); if(r < 0) { cprintf("serve_write: failed to lookup open file id\n"); return r; } nbytes = MIN(req->req_n, PGSIZE - (sizeof(int) + sizeof(size_t))); nbytes = file_write(o->o_file, (void *) req->req_buf, nbytes, o->o_fd->fd_offset); if (nbytes >= 0) { o->o_fd->fd_offset += nbytes; } return nbytes; //panic("serve_write not implemented"); }
如果我说我在这个鬼地方panic了三天,不停的提示0xef40300地址处发生错误,我靠...原来是因为我下面这个解答敲出来的时候, 中间迭代变量 j 写成了 i ... 血泪的 i j k !! 道友们如果不想自己被自己坑的话,以后还是多注意点...能不用 ijk 就不要用.段代码都不要用...自己好好想个好点的变量名,不要看别人写ijk自己也就跟着写. 我以前抗争了一段时间,后面又开始用ijk,觉得只要代码短点就没事了. 但是长期coding累了之后就特别容易发生错误.
千万千万别用一个字母去做变量名...
// Copy the mappings for shared pages into the child address space. static int copy_shared_pages(envid_t child) { // LAB 5: Your code here. int r = 0; uint32_t i, j, pn; for (i = PDX(UTEXT); i < PDX(UXSTACKTOP); i++) { if(uvpd[i] & PTE_P) { for(j = 0; j < NPTENTRIES; j++) { pn = PGNUM(PGADDR(i, j, 0)); if(pn == PGNUM(UXSTACKTOP - PGSIZE)) { continue; } if((uvpt[pn] & PTE_P) && (uvpt[pn] & PTE_SHARE)) { if( (r = sys_page_map(0, (void *)(pn * PGSIZE), child, (void *)(pn * PGSIZE), uvpt[pn] & PTE_SYSCALL)) < 0) { return r; } } } } } return 0; }
找到trap_dispatch()
对号入座.
// Handle keyboard and serial interrupts. // LAB 5: Your code here. if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) { serial_intr(); return; } if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) { kbd_intr(); return; }
测试
目前shell 不知道怎么的,出现了一个找不到设备的bug提示信息.
先把lab5放出来. 还有很多不满意的地方, 后续有机会这几天只要没事就肯定会update : )
panic 几天没关系, 咱没在怕的, 加油~