Pintos Task 2: User Programs
Feroz Salam
Imperial College London
February 10, 2010
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
1 / 17
Introduction
Goal
Get user programs safely working on Pintos
Tasks
i Set up stack and pass arguments ii Implement process waiting iii Implement system calls
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
2 / 17
Getting Started
Does Task 1 need to be complete?
No code from Task 1 is required Some knowledge of threading system will be necessary Can start with fresh code/build upon existing threading code
Testing
Important to read Testing section again
With a large number of test cases (70+), its useful to know how to run single tests independently.
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
3 / 17
Important Files
Files to modify:
Most of your work will be done in the userprog directory. i process.c
Handles loading, execution and exit of processes Set up stack code goes here Process waiting code goes here
ii syscall.c
All system calls go here Initial code exits immediately
iii exception.c
Contains exception handling code May/may not modify this depending on implementation
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
4 / 17
Important Files
Files with useful functions
i pagedir.c
pagedir get page() used for validating user memory references
ii threads/vaddr.h
is user vaddr() used to validate user provided pointers
iii lib/string.c
strtok r() used to tokenise strings
Using these functions will be explained later as required.
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
5 / 17
User Programs in Unix
What happens when a user types this command at the shell?
vector27% cp -r /usr/bin/temp . i The shell parses user input. ii The shell calls fork() and execve(cp, argv, env) with stack set up iii cp uses the le sytem interface to copy les iv cp (might) print to the console v cp exits, possibly returning an exit code to a parent process Pintos should work very similarly at the end of Project 2.
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
6 / 17
Chain of Execution (in Pintos)
threads/init.c
main() -> run actions(argv) run actions() -> run task(argv) run task() -> process wait(process execute(task))
userprog/process.c
process execute() creates a thread that runs start process(filename,...) start process() -> load(filename) load() does all remaining work to load user process (setting up stack, data, code, etc.)
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
7 / 17
Project Requirements
Passing arguments Safe memory access Process waiting System calls (a long list) Process termination messages Denying writes to les in use as executables
Note
This is just a list of work that you will have to do, not an order of implementation.
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
8 / 17
Parsing Arguments
What?
Have to parse command line string cp [Link] ../[Link] into
cp [Link] ../[Link]
How?
Any way you like, really. Just FYI, strtok r() in lib/string.c might be useful
Where?
Anywhere before you load the process, obviously Spec says in process execute()
Feroz Salam (Imperial College London) Pintos Task 2: User Programs February 10, 2010 9 / 17
Setting Up The Stack
The stack needs to be set up very carefully...
i Push the arguments onto the stack, one by one, in reverse order ii Push a null pointer sentinel (0) iii Push pointers to the arguments (again in reverse) iv Push a pointer to the rst pointer v Push the number of arguments vi Push a fake return address (0) The hex dump() function in lib/stdio.h may be useful for seeing the layout of the stack in case things go wrong
Where?
In start process() after the interrupt frame (containing the address of the stack pointer) is initialized
Feroz Salam (Imperial College London) Pintos Task 2: User Programs February 10, 2010 10 / 17
Handling User Pointers
When an user program makes a system call, the kernel will have to deal dereferencing any pointers required to pass arguments. This can be problematic because of
i NULL pointers ii pointers to unmapped user memory iii pointers to kernel addresses
Dealing with such cases is easy - once identied, kill the process causing the problem and free any resources held by it. Watch out for special problems posed by buers and strings
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
11 / 17
Implementing Safe Memory Accesses
Option 1: Verify Before Dereference
Verify the pointer before you dereference it (simpler) Is it in the user space? (is user vaddr() in threads/vaddr.h) Is it mapped? (pagedir get page() in userprog/pagedir.c) Dont forget these checks when reading from buers and strings
Option 2: Modify Fault Handler
Only check that address is in user space Invalid pointers will trigger a page fault Modify the page fault handler to kill running process Gives better performance Explained in more detail in Section 3.1.5 of the specication
Feroz Salam (Imperial College London) Pintos Task 2: User Programs February 10, 2010 12 / 17
System Calls
System calls allow user processes to ask the kernel to execute operations that they dont have permission to execute.
In Pintos
You will have to implement the syscall handler() in syscall.c First, read the syscall number at the stack pointer (f->esp) Read the arguments above the stack pointer Pass to the appropriate function (syscall numbers are dened in lib/syscall-nr.h) Return result to f->eax Try to avoid duplicating code all over the handler, neater solutions mean fewer mistakes and code that is easier to debug
Feroz Salam (Imperial College London) Pintos Task 2: User Programs February 10, 2010 13 / 17
Using lesys
Pintos comes with a basic, built-in lesys implementation in file.h and filesys.h. You do not need to modify this Syscalls use le descriptors (int), but the lesystem implementation uses pointers to le structs. Mappings are left to you. When modifying les in the lesystem, make sure that no other processes are able to make changes. No ner synchronisation is expected. Special le descriptors for the console: STDOUT FILENO for writing to console STDIN FILENO for reading from console
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
14 / 17
Process Waiting
process wait()
Calling function blocks (using synchronisation) waiting for the child process with the provided pid to exit. wait system call is trivial once it is implemented Returns the exit status of the child (or (-1) if error) Most work of all the functions Read the specication carefully before starting work on this, and ensure you start work on process wait() as soon as possible
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
15 / 17
Denying Writes to Executables
Code that is currently running should not be modied Use file deny write to prevent writes to an open le Use file allow write to re-enable writes Executables should be kept open and unwriteable for as long as the process is running
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
16 / 17
Suggested Order of Implementation
Following the order of implementation in the specication will save you a lot of time i Temporarily set up the stack to avoid immediate page faults ii Implement safe user memory access iii Set up a basic syscall handler iv Implement exit syscall v Implement write to console vi Change process wait to an innite loop (at this point, processes will execute but will not exit - being able to run individual tests and look at their .output les will be an invaluable skill) vii Start implementing everything else, beginning with argument passing and process wait()
Feroz Salam (Imperial College London)
Pintos Task 2: User Programs
February 10, 2010
17 / 17