main.c: main is start ... init.c: mips_init() is called Physical memory: 65536K available, base = 65536K, extended = 0K to memory 80401000forstruct page directory. to memory 80431000forstruct Pages. pmap.c: mips vm init success pageout: @@@___0x7f3fe000___@@@ ins a page pageout: @@@___0x40d000___@@@ ins a page FS is running FS can do I/O pageout: @@@___0x7f3fe000___@@@ ins a page pageout: @@@___0x407000___@@@ ins a page superblock is good diskno: 0 diskno: 0 read_bitmap is good diskno: 0 alloc_block is good file_open is good file_get_block is good file_flush is good file_truncate is good diskno: 0 file rewrite is good serve_open 00000400 ffff000 0x2 open is good read is good father read is good && father_fd == 0 father_fd's offset == 41 [00000400] destroying 00000400 [00000400] free env 00000400 i am killed ... child read is good && child_fd == 0 child_fd's offset == 41 [00001402] destroying 00001402 [00001402] free env 00001402 i am killed ...
// Read the sector in turn while (secno < max) { temp = wait_ide_ready(); // Step 1: Write the number of operating sectors to NSECT register temp = 1; panic_on(syscall_write_dev(&temp, MALTA_IDE_NSECT, 1));
// Step 2: Write the 7:0 bits of sector number to LBAL register temp = secno & 0xff; panic_on(syscall_write_dev(&temp, MALTA_IDE_LBAL, 1));
// Step 3: Write the 15:8 bits of sector number to LBAM register /* Exercise 5.3: Your code here. (1/9) */ temp = (secno >> 8) & 0xff; panic_on(syscall_write_dev(&temp, MALTA_IDE_LBAM, 1));
// Step 4: Write the 23:16 bits of sector number to LBAH register /* Exercise 5.3: Your code here. (2/9) */ temp = (secno >> 16) & 0xff; panic_on(syscall_write_dev(&temp, MALTA_IDE_LBAH, 1));
// Step 5: Write the 27:24 bits of sector number, addressing mode // and diskno to DEVICE register temp = ((secno >> 24) & 0x0f) | MALTA_IDE_LBA | (diskno << 4); panic_on(syscall_write_dev(&temp, MALTA_IDE_DEVICE, 1));
// Step 6: Write the working mode to STATUS register temp = MALTA_IDE_CMD_PIO_READ; panic_on(syscall_write_dev(&temp, MALTA_IDE_STATUS, 1));
// Step 7: Wait until the IDE is ready temp = wait_ide_ready();
// Step 8: Read the data from device for (int i = 0; i < SECT_SIZE / 4; i++) { panic_on(syscall_read_dev(dst + offset + i * 4, MALTA_IDE_DATA, 4)); }
// Step 9: Check IDE status panic_on(syscall_read_dev(&temp, MALTA_IDE_STATUS, 1));
offset += SECT_SIZE; secno += 1; } }
/* Overview: * write data to IDE disk. * * Parameters: * diskno: disk number. * secno: start sector number. * src: the source data to write into IDE disk. * nsecs: the number of sectors to write. * * Post-Condition: * Panic if any error occurs. * * Hint: Use syscalls to access device registers and buffers. * Hint: Use the physical address and offsets defined in 'include/malta.h'. */ voidide_write(u_int diskno, u_int secno, void *src, u_int nsecs) { uint8_t temp; u_int offset = 0, max = nsecs + secno; panic_on(diskno >= 2);
// Write the sector in turn while (secno < max) { temp = wait_ide_ready(); // Step 1: Write the number of operating sectors to NSECT register /* Exercise 5.3: Your code here. (3/9) */ temp = 1; panic_on(syscall_write_dev(&temp, MALTA_IDE_NSECT, 1));
// Step 2: Write the 7:0 bits of sector number to LBAL register /* Exercise 5.3: Your code here. (4/9) */ temp = secno & 0xff; panic_on(syscall_write_dev(&temp, MALTA_IDE_LBAL, 1));
// Step 3: Write the 15:8 bits of sector number to LBAM register /* Exercise 5.3: Your code here. (5/9) */ temp = (secno >> 8) & 0xff; panic_on(syscall_write_dev(&temp, MALTA_IDE_LBAM, 1));
// Step 4: Write the 23:16 bits of sector number to LBAH register /* Exercise 5.3: Your code here. (6/9) */
// Step 6: Write the working mode to STATUS register /* Exercise 5.3: Your code here. (8/9) */ temp = MALTA_IDE_CMD_PIO_WRITE; panic_on(syscall_write_dev(&temp, MALTA_IDE_STATUS, 1));
// Step 7: Wait until the IDE is ready temp = wait_ide_ready();
// Step 8: Write the data to device for (int i = 0; i < SECT_SIZE / 4; i++) { /* Exercise 5.3: Your code here. (9/9) */ panic_on(syscall_write_dev(src + offset + i * 4, MALTA_IDE_DATA, 4)); }
// Step 9: Check IDE status panic_on(syscall_read_dev(&temp, MALTA_IDE_STATUS, 1));
offset += SECT_SIZE; secno += 1; } }
T4
因为0号磁盘块存的是磁盘的信息 ,不可以被清除,也就是不能释放置为空闲。
1 2 3 4 5 6 7 8 9 10 11 12
voidfree_block(u_int blockno) { 186// You can refer to the function 'block_is_free' above. 187// Step 1: If 'blockno' is invalid (0 or >= the number of blocks in 'super'), return. 188/* Exercise 5.4: Your code here. (1/2) */ 189if (blockno == 0 || blockno >= super->s_nblocks) { 190return; 191 } 192// Step 2: Set the flag bit of 'blockno' in 'bitmap'. 193// Hint: Use bit operations to update the bitmap, such as b[n / W] |= 1 << (n % W). 194/* Exercise 5.4: Your code here. (2/2) */ 195 bitmap[blockno / 32] |= 1 << (blockno % 32); 196 }
// Step 1: Iterate through all existing blocks in the directory. for (int i = 0; i < nblk; ++i) { int bno; // the block number // If the block number is in the range of direct pointers (NDIRECT), get the 'bno' // directly from 'f_direct'. Otherwise, access the indirect block on 'disk' and get // the 'bno' at the index. /* Exercise 5.5: Your code here. (1/3) */ if (i < NDIRECT) { bno = dirf->f_direct[i]; } else { bno = ((int *)(disk[dirf->f_indirect].data))[i]; }
// Get the directory block using the block number. structFile *blk = (struct File *)(disk[bno].data);
// Iterate through all 'File's in the directory block. for (struct File *f = blk; f < blk + FILE2BLK; ++f) { // If the first byte of the file name is null, the 'File' is unused. // Return a pointer to the unused 'File'. /* Exercise 5.5: Your code here. (2/3) */ if (f->f_name[0] == '\0') { return f; } } }
// Step 2: If no unused file is found, allocate a new block using 'make_link_block' function // and return a pointer to the new block on 'disk'. /* Exercise 5.5: Your code here. (3/3) */ int bno = make_link_block(dirf, nblk); return (struct File *)(disk[bno].data); returnNULL; }
intmap_block(u_int blockno) { // Step 1: If the block is already mapped in cache, return 0. // Hint: Use 'block_is_mapped'. /* Exercise 5.7: Your code here. (1/5) */ if (block_is_mapped(blockno)) { return0; }
// Step 2: Alloc a page in permission 'PTE_D' via syscall. // Hint: Use 'disk_addr' for the virtual address. /* Exercise 5.7: Your code here. (2/5) */ return syscall_mem_alloc(0, disk_addr(blockno), PTE_D); }
// Overview: // Unmap a disk block in cache. voidunmap_block(u_int blockno) { // Step 1: Get the mapped address of the cache page of this block using 'block_is_mapped'. void *va; /* Exercise 5.7: Your code here. (3/5) */ va = block_is_mapped(blockno);
// Step 2: If this block is used (not free) and dirty in cache, write it back to the disk // first. // Hint: Use 'block_is_free', 'block_is_dirty' to check, and 'write_block' to sync. /* Exercise 5.7: Your code here. (4/5) */
if (!block_is_free(blockno) && block_is_dirty(blockno)) { write_block(blockno); }
// Step 3: Unmap the virtual address via syscall. /* Exercise 5.7: Your code here. (5/5) */ panic_on(syscall_mem_unmap(0, va));
intdir_lookup(struct File *dir, char *name, struct File **file) { // Step 1: Calculate the number of blocks in 'dir' via its size. u_int nblock; /* Exercise 5.8: Your code here. (1/3) */
nblock = dir->f_size / BLOCK_SIZE;
// Step 2: Iterate through all blocks in the directory. for (int i = 0; i < nblock; i++) { // Read the i'th block of 'dir' and get its address in 'blk' using 'file_get_block'. void *blk; /* Exercise 5.8: Your code here. (2/3) */
try(file_get_block(dir, i, &blk)); structFile *files = (struct File *)blk;
// Find the target among all 'File's in this block. for (struct File *f = files; f < files + FILE2BLK; ++f) { // Compare the file name against 'name' using 'strcmp'. // If we find the target file, set '*file' to it and set up its 'f_dir' // field. /* Exercise 5.8: Your code here. (3/3) */ if (strcmp(name, f->f_name) == 0) { *file = f; f->f_dir = dir; return0; } } }
// Step 1: Alloc a new 'Fd' using 'fd_alloc' in fd.c. // Hint: return the error code if failed. structFd *fd; /* Exercise 5.9: Your code here. (1/5) */ r = fd_alloc(&fd); if (r) { return r; }
// Step 2: Prepare the 'fd' using 'fsipc_open' in fsipc.c. /* Exercise 5.9: Your code here. (2/5) */ r = fsipc_open(path, mode, fd); if (r) { return r; }
// Step 3: Set 'va' to the address of the page where the 'fd''s data is cached, using // 'fd2data'. Set 'size' and 'fileid' correctly with the value in 'fd' as a 'Filefd'. char *va; structFilefd *ffd; u_int size, fileid; /* Exercise 5.9: Your code here. (3/5) */ va = fd2data(fd); ffd = (struct Filefd *)fd; size = ffd->f_file.f_size; fileid = ffd->f_fileid;
// Step 4: Map the file content using 'fsipc_map'. for (int i = 0; i < size; i += PTMAP) { /* Exercise 5.9: Your code here. (4/5) */
r = fsipc_map(fileid, i, va + i); if (r) { return r; } }
// Step 5: Return the number of file descriptor using 'fd2num'. /* Exercise 5.9: Your code here. (5/5) */ // if (mode & O_APPND) // seek(fdnum, size); return fd2num(fd); }
// Similar to the 'write' function below. // Step 1: Get 'fd' and 'dev' using 'fd_lookup' and 'dev_lookup'. structDev *dev; structFd *fd; /* Exercise 5.10: Your code here. (1/4) */ if ((r = fd_lookup(fdnum, &fd)) < 0) { return r; }
// Step 2: Check the open mode in 'fd'. // Return -E_INVAL if the file is opened for writing only (O_WRONLY). /* Exercise 5.10: Your code here. (2/4) */ if ((fd->fd_omode & O_ACCMODE) == O_WRONLY) { return -E_INVAL; }
// Step 3: Read from 'dev' into 'buf' at the seek position (offset in 'fd'). /* Exercise 5.10: Your code here. (3/4) */ r = dev->dev_read(fd, buf, n, fd->fd_offset);
// Step 4: Update the offset in 'fd' if the read is successful. /* Hint: DO NOT add a null terminator to the end of the buffer! * A character buffer is not a C string. Only the memory within [buf, buf+n) is safe to * use. */ /* Exercise 5.10: Your code here. (4/4) */ if (r > 0) { fd->fd_offset += r; }
return r; }
T11
1 2 3 4 5 6 7 8 9 10
voidserve_remove(u_int envid, struct Fsreq_remove *rq) { // Step 1: Remove the file specified in 'rq' using 'file_remove' and store its return value. int r; /* Exercise 5.11: Your code here. (1/2) */ r = file_remove(rq->req_path);
// Step 2: Respond the return value to the caller 'envid' using 'ipc_send'. /* Exercise 5.11: Your code here. (2/2) */ ipc_send(envid, r, 0, 0); }
intfsipc_remove(constchar *path) { // Step 1: Check the length of 'path' using 'strlen'. // If the length of path is 0 or larger than 'MAXPATHLEN', return -E_BAD_PATH. /* Exercise 5.12: Your code here. (1/3) */ if (path[0] == '\0' || strlen(path) >= MAXPATHLEN) { return -E_BAD_PATH; }
// Step 2: Use 'fsipcbuf' as a 'struct Fsreq_remove'. structFsreq_remove *req = (struct Fsreq_remove *)fsipcbuf;
// Step 3: Copy 'path' into the path in 'req' using 'strcpy'. /* Exercise 5.12: Your code here. (2/3) */ strcpy((char *)req->req_path, path);
// Step 4: Send request to the server using 'fsipc'. /* Exercise 5.12: Your code here. (3/3) */