1. 程式人生 > 實用技巧 >[OS][MIT 6.828] Lab 5: File system, Spawn and Shell

[OS][MIT 6.828] Lab 5: File system, Spawn and Shell

File system preliminaries

Disk space division: Inode regions and data regions. (P.S. not for JOS)
Sectors and Blocks: Sector is a term used by disk, block is a term used by operating system.
Superblocks

The File System

block cache

Block caache is actually a reserved large, fixed 3GB region of the file system environment's address space, from 0x10000000 (DISKMAP) up to 0xD0000000 (DISKMAP+DISKMAX). It's a "memory mapped" version of the disk.

void* diskaddr(uint32_t blockno) // Return the virtual address of this disk block.
bool va_is_mapped(void *va) // Is this virtual address mapped?
bool va_is_dirty(void *va) // Is this virtual address dirty?
static void bc_pgfault(struct UTrapframe *utf) // Fault any disk block that is read in to memory by loading it from disk.
void flush_block(void *addr) // Flush the contents of the block containing VA out to disk if necessary, then clear the PTE_D bit.
(free block) bitmap
bool block_is_free(uint32_t blockno) /* Check to see if the block bitmap indicates that block 'blockno' is free. */
void free_block(uint32_t blockno) // Mark a block free in the bitmap.
int alloc_block(void) // Search the bitmap for a free block and allocate it.
file system structures
/* Find the (disk block number) slot for the 'filebno'th block in file 'f'. Set '*ppdiskbno' to point to that slot.
   The slot will be one of the f->f_direct[] entries, or an entry in the indirect block.
   When 'alloc' is set, this function will allocate an indirect block if necessary. */
static int file_block_walk(struct File *f, uint32_t filebno, uint32_t **ppdiskbno, bool alloc)

// Set *blk to the address in memory where the filebno'th block of file 'f' would be mapped.
int file_get_block(struct File *f, uint32_t filebno, char **blk)

// Try to find a file named "name" in the very dir. Don't search in the sub directory of dir
static int dir_lookup(struct File *dir, const char *name, struct File **file)

// Allocate a free 'File' structre in dir. Set *file to point at that free File structure in dir.
static int dir_alloc_file(struct File *dir, struct File **file)

// Evaluate a path name, starting at the root. On success, set *pf to the file we found and set *pdir to the directory the file is in.
static int walk_path(const char *path, struct File **pdir, struct File **pf, char *lastelem)
file operations
int file_create(const char *path, struct File **pf) // Create "path".  On success set *pf to point at the file and return 0.
int file_open(const char *path, struct File **pf) // Open "path".  On success set *pf to point at the file and return 0.
ssize_t file_read(struct File *f, void *buf, size_t count, off_t offset)
int file_write(struct File *f, const void *buf, size_t count, off_t offset)
static int file_free_block(struct File *f, uint32_t filebno) // Remove a block from file f.
static void file_truncate_blocks(struct File *f, off_t newsize)
int file_set_size(struct File *f, off_t newsize)
void file_flush(struct File *f)
void fs_sync(void) // Sync the entire file system.

summary of file system

1)some relevant structs
/* Environment operate with Fd, an environment can open at most MAXFD files.
   File represent file on disk, fs environment operate file with File.
   OpenFile connect Fd and File, server(i.e., fs environment) can have at most MAXOPEN openfiles.
   In file system, Dev is a file device.*/

struct Fd
struct OpenFile
struct File
struct Dev
2)server side(fs environment)
  1. serve_init() : Initialize struct OpenFile opentab[MAXOPEN].
  2. fs_init() : (1)Find a disk. (2)Set super block and bitmap.
  3. bc_init() : (1)Set up user level page fault handler which can load 1 block from disk into memory. (2)Load super block.

Up to here the file system is ready to work. Here are the steps the server follows to fulfill a request from other environment.

  1. ipc_recv() : Receive a request from other environment.
  2. serve_*() : Search opentab for the specific file.
  3. file_*() : Invoked by serve_*() and fulfill the specific job on the file.
  4. ipc_send() : Return the result.
3)client side(other environment)

We will use read as an example.

  1. fd.c/read() : The top interface invoked by non-fs environment. Search FDTABLE for the file and devtab for the device type, read the found file using the 'read routine' stored in the found device. Here, the device is disk.
  2. file.c/devfile_read() : Make an FSREQ_READ request to the file system server after filling fsipcbuf.
  3. fsipc() : Send a request with ipc_send() and receive result with ipc_recv().

Spawning Processes

Steps to spawn a child process

  1. Open the ELF image file.
  2. Read ELF header into memory.
  3. Allocate a PCB(i.e., a slot in array envs) using sys_exofork().
  4. Set up entry point(eip) and initialize stack.
  5. Load ELF_PROG_LOAD segments into memory and map them into address space.
  6. Close the image file and copy shared pages from parent into child process.
  7. Set up trapframe and status.