CS 134

Note: This design was reformatted as the original student-submitted Markdown did not render well.

Design

Struct Designs

process struct

  • struct filetable *filetable: pointer to file table
  • parent process
  • struct cv *wait_cv
  • struct process_info *process_info

process_info struct

(Used to pass along info in processes instead of passing an entire process or pointer to -- since there can be copying issues or race conditions)

  • current working directory
  • pid
  • exit code
  • has_exited

filetable struct

  • struct lock *lock: pointer to lock for file table operations
  • struct openfile **openfiles: array of pointers to open files
  • Note: we'll also define a constant for the max size of the array

openfile struct:

  • vnode * : pointer to the vnode representing the file
  • int flags: flags for what we are allowed to do with the file
  • off_t offset: The file offset for the file the struct is referring to
  • int ref_count: We want to count the number of file descriptors that point to the file so we can remove the object when ref count is 0.
  • struct lock *: We want a lock to manage any race conditions or concurrency issues while accessing the files.

Function Designs

Functions implemented: open, read, write, lseek, close, dup2, chdir, __getcwd

open

int open(const char *filename, int flags, ...);

  • Iterate through and find new spot to allocate file descriptor
  • Create new openfile structure with given flags
  • Use vfs_open to open the file
  • Add the openfile to the process's file table
  • Return the file descriptor

read

ssize_t read(int filehandle, void *buf, size_t size);

  • Acquire lock
  • Use VOP_READ to read the file (with given offset and other info provided in uio)
  • Update the file offset
  • Release lock
  • Return the number of bytes read

write

ssize_t write(int filehandle, const void *buf, size_t size);

  • Acquire lock
  • Use VOP_WRITE write to the file at the current offset (provided in uio)
  • Update the file offset
  • Release lock
  • Return the number of bytes written

lseek

off_t lseek(int filehandle, off_t pos, int code);

  • Acquire lock
  • Calculate the new offset based on the current offset
  • Update the file offset
  • Release lock
  • Return the new offset

close

int close(int filehandle);

  • Validate the file descriptor
  • Remove the pointer to openfile from the process's file descriptor table by setting pointer to NULL
  • Decrement the openfile's reference count
  • If the reference count reaches zero, close the vnode and free the openfile struct
  • Delete openfile from file table

dup2

int dup2(int filehandle, int newhandle);

  • If file descriptors are the same, return immediately
  • If the new file descriptor is already in use, close it
  • Copy the openfile pointer from the old file descriptor to the new one
  • Increment the openfile's reference count

chdir

int chdir(const char *path);

  • Get directory vnode with vfs_getcurdir
  • Update the process's current working directory
  • Release the old directory vnode if it exists

__getcwd

ssize_t __getcwd(char *buf, size_t buflen);

  • Use vfs_getcurdir to get the current working directory path
  • Copy the path to the user-provided buffer
  • Return the length of the path

fork

pid_t fork(void);

  • Duplicate the calling process proc struct
  • Copy over parent address space
  • Copy parent's open file descriptors, update reference counts
  • Copy parent cwd
  • Return 1 to parent (later will return child PID to parent)

_exit

__DEAD void _exit(int code);

  • Close open file descriptors
  • Free process file descriptor table
  • Free memory resources
  • Mark hasExited on the process to true
  • Set exit code
  • Wake up waiting parents (phase 2)

getpid

pid_t getpid(void);

Returns pid from the current process

execv

int execv(const char *prog, char *const *args);

  • Copy args from user space to kernel space
  • Open program file
  • Create new vaddr space, load program in
  • Copy args over to new stack
  • Return to usermode

waitpid

pid_t waitpid(pid_t pid, int *returncode, int flags);

  • Acquire lock
  • cv_wait until child has exited
  • Clean up child
  • Release lock
  • Return pid

(When logged in, completion status appears here.)