In this lab you will implement user processes and system calls.
As supplied, Pintos is incapable of running user processes and only implements two systems calls. Pintos does, however, have the ability to load ELF binary executable, and has a fully functioning page-based, non- virtual memory management system.
There are three parts to this lab; each depends on the previous one.
- Allow simple user process to run.
- Support argument passing to user processes.
- Implement seven new systems calls.
- Follow instructions from Lab 1 to get Oracle Virtual Box installed if you have not already done so.
Download and install the lab specific virtual appliance: https://classes.soe.ucsc.edu/cmps111/Fall17/SECURE/CMPS111-Lab3.ova
Import this appliance into Virtual Box using the “File->Import Appliance” menu: Select the downloaded .ova and accept all defaults.
Start the virtual appliance:
Click the button to start the lab appliance, an Ubuntu 32bit Desktop instance.
Check the Pintos installation works:
Open a terminal window (the icon) and enter the following commands:
$ cd pintos/src/userprog ( always work in this directory )
$ make ( builds pintos )
Now run a test:
$ pintos -v -k -T 60 –qemu –filesys-size=2 \
-p build/tests/userprog/args-none \
-a args-none – -q -f run ‘args-none’
The same test can also be run using the following command, but more sophisticated tests will need to be run in the long form above, passing arguments as required inside the single quotes. E.g. ‘args-many 1 2 3‘
$ runtest args-none
$ make check ( runs the required functional tests - see below )
$ make grade ( tells you what grade you will get - see below )
In certain circumstances, “make grade” will fail to complete. If this happens to you, simply run the following command instead:
$ grade ( runs make grade repeatedly until it completes )
Pinto is a Unix-like operating system and should implement the standard Unix / C calling convention. To understand how arguments are passed to Unix / C programs, consider the command:
/bin/ls -l foo bar
Also recall that the prototype for a C program entry point is:
int main(int argc, char *argv)
Where argc is the number of arguments passed to the program (including the program name) and argv is an array containing pointers to each of the arguments stored as null-terminated character arrays.
To execute this program with the supplied arguments, we need to do the following:
- Break this command into words: ”/bin/ls”, ”-l”, ”foo”, and ”bar”.
- Place these words at the top of the stack, in right to left order.
Push onto the stack the _address _of each string plus a null pointer sentinel, in right-to-left order.
* These are the elements of argv. The null pointer sentinel ensures that argv[argc] is a null pointer, as required by the C standard. The order ensures that argv is at the lowest virtual address. Word-aligned accesses are faster than unaligned accesses, so for best performance, round the stack pointer down to a multiple of 4 before the first push.
- Push argv (the address of argv) and argc, in that order.
- Finally, push a fake “return address”. Although the entry function will never return, its stack frame must have the same structure as any other.
The figure below shows the contents in the stack before executing the user program. We assume here that
PHYS_BASE is 0xc0000000.
As shown above, your code should start with the stack at the very top of the user virtual address space, in the page just below virtual address PHYS_BASE ( defined in threads/vaddr.h ).
Most user programs require services provided by Pintos; they access those capabilities by making system calls. To support this feature, you will need to extend the existing system call implementation in userprog/syscall.c.
The system calls of interest in this lab are:
- create : Creates a new file. Return true if successful and false otherwise.
- open : Open a file and return the corresponding file descriptor (i.e. an integer handle). Note that file descriptor 0 is reserved for standard input and file descriptor 1 is reserved for standard output.
- read : Read a specified number of bytes from an existing, open file into a buffer in the user program, returning the number of bytes actually read, or -1 if read failed.
- write: Write a specified number of bytes to an open file from a buffer in the user program. Return the number of bytes actually written or -1 if an error occurs.
- close : Close an open file.
- exec : Starts the execution of a user program and returns the ID of the newly created child process if successful. The parent process should not return from the exec system call until it knows whether the child process has successfully loaded its executable code.
- wait : Waits for a child process to complete and retrieves the child’s exit value.
Note that the above descriptions are a guide only, your system calls must do whatever the tests demand they do!
- Give Pintos the ability to execute user processes mapped one-to-one with kernel threads.
Pass the following test:
* args-none Arguments to User Processes:
- Allow Pintos user processes to accept command line arguments.
Pass the following tests:
args-dbl-space System Calls:
Implement the create, open, read, write, close, exec, and wait function calls.
Pass the following tests:
In a command prompt:
$ cd pintos/src/userprog
$ make submit
This creates a gzipped tar archive named CMPS111-Lab3.tar.gz in the home directory.
In addition to submitting modified and new source files, you are required to write a short report on your work. This report should contain at least:
- A defense of the design rationale behind your code
- Details of tests your submission fails and what investigations you undertook to try and find out why
If you keep a simple journal as you work your way through this lab, writing the report will be easy - it’s essentially a tidied up version of your journal.
The following aspects will be assessed:
- (80%) Does it work?
a. User Processes (30%) b. Argument Passing (10%) c. System Calls (40%)
Marks awarded for:
* Compilation free of errors and/or warnings.
Evidence of original work - i.e. not simply having copied other peoples code.
Marks deducted for:
- Compilation warnings in code you wrote.
- Not giving credit to on-line resources you “borrowed” code segments from.
- Poor factorization - e.g. huge functions that do way too much.
- “Spaghetti Code” - i.e. code related to one functional area scattered all over the place.
- Magic numbers, nested conditionals, duplication, inconsistent naming, and other assorted code nastiness.
- Your code partially shows this, but the report is where you convince me.
Marks awarded for:
* Clearly stating which requirements were met and which were not.
- Concise description of development process.
- Details of testing methodology.
- An observation of what was easy, what was hard, where problems arose, how they were overcome.
- Reflection on how you might improve or extend your solution.