Lab Assignment 1 - System Calls - Design Doc
Overview
The goal of this assignment is to implement an interface for users to interact with persistent media or with other I/O devices, without having to distinguish between their types.
Major parts
File interface: The file interface provides an abstraction for the user that doesn’t depend on the type of file. This will allow user applications to interact with different types of files without large changes in the code. For example, the method for attaining bytes will be the same when reading input for a file or from stdin.
System calls: The syscall interface provides a barrier for the kernel to validate user program input. This way, we can keep the I/O device state consistent. No user program can directly affect the state of the kernel’s data structures. Furthermore, when we are already in the kernel code, we don’t have to go through the syscall interface, which cuts down on superfluous error checking for trusted code.
In-depth analysis and implementation
File interface
Bookkeeping
-
include/kernel/fs.hprovides astruct filethat we can use to back each file descriptor. -
include/kernel/console.hprovides consolestruct files forstdinandstdout.
Process view
Each process will have an array of open files (bounded by PROC_MAX_FILE) in the process struct (struct proc). The file descriptor will be the respective index into the file table. For example, stdin is typically file descriptor 0, so the corresponding file struct will be the first element. A system call can use proc_current() to get a pointer to the process control block (i.e., the struct proc) for the currently running process.
System calls
We need to parse arguments from the user and validate them (we never trust the user!). There are a few useful functions provided by osv:
-
bool fetch_arg(void *arg, int n, sysarg_t *ret): Givenargs, fetches thenth argument and stores it at*ret. Returnstrueif fetched successfully, orfalseif thenth argument is unavailable. -
static bool validate_str(char *s): Given a strings, checks whether the whole string is within a valid memory region of the process. -
static bool validate_ptr(void *ptr, size_t size): Given a bufferptrof sizesize, checks whether the buffer is within a valid memory region of the process.
Because all of our system calls will be dealing with files, we think it will be useful to add a function that allocates a file descriptor, and another that validates a file descriptor:
static int alloc_fd(struct file *f): Given a pointer to a file, looks through the process’s open file table to find an available file descriptor, and stores the pointer there. Returns the chosen file descriptor.static bool validate_fd(int fd): Given a file descriptor, checks that it is valid (i.e., that it is in the open file table for the current process).
The main goals of the sys_* functions are to do argument parsing+validation, and then call the associated fs_*_file functions:
-
sys_write/sys_read:- Writes or reads a file.
- Changes the
f_posof the respective file struct. - Return values are specified by Assignment 1 (also in
include/lib/usyscall.h).
-
sys_open:- Finds an open entry in the process’s open file table and stores a pointer to the file opened by the file system.
- If no open spot is available, this should be considered a failure to allocate memory.
- Return values are specified by Assignment 1 (also in
include/lib/usyscall.h).
-
sys_close:- Closes a file.
- Releases the file from the process and clears out its entry in the process’s open file table.
- Returns values specified by Assignment 1 (also in
include/lib/usyscall.h).
-
sys_readdir:- Reads a directory.
- Return values are specified by Assignment 1 (also in
include/lib/usyscall.h).
-
sys_dup:- Finds an open entry in the process’s open file table and stores a pointer to the same file struct as the descriptor being duplicated.
- If no open spot is available, this should be considered a failure to allocate memory.
- Needs to update the reference count of the file through
fs_reopen_file(). - Return values are specified by Assignment 1 (also in
include/lib/usyscall.h).
-
sys_fstat:- Retrieves statistics of a file from
struct fileand itsstruct inode. - Return values are specified by Assignment 1 (also in
include/lib/usyscall.h).
- Retrieves statistics of a file from
File system
We will need to use several file system functions declared in include/kernel/fs.h. These are:
fs_open_file: opens a filefs_reopen_file: increment a file’s reference countfs_read_file: performs a read operation on the given filefs_write_file: performs a write operation on the given filefs_close_file: closes an open filefs_readdir: reads a directory
Risk analysis
Unanswered questions
-
What happens when two different processes try to update data on the same file?
-
What happens when the user or the kernel has the maximum number of files open?
Staging of work
We plan to implement the work in this lab as follows:
-
Implement the per-process open file table.
-
Retrieve and validate syscall inputs.
-
Call the respective file functions.
We will also update process initialization so that file descriptors 0 and 1 point to stdin and stdout, respectively, from console.h.
Time estimation
When you author your own design documents in future lab assignments, you will include a time estimate for the various tasks. You might practice your estimation skills by making estimates for this lab and keeping track of your time to complete them.
- File interface (__ hours)
- process portion (__ hours)
- System calls (__ hours)
sys_open(__ hours)sys_read(__ hours)sys_write(__ hours)sys_close(__ hours)sys_readdir(__ hours)sys_dup(__ hours)sys_fstat(__ hours)
- Edge cases and error handling (__ hours)