You are on page 1of 17

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 foo.txt ../bar.txt into
cp foo.txt ../bar.txt

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

You might also like