CS140 Project Session
User programsUser programs
Syed Akbar Mehdi
(based on Megan Wachs slides Win-08)
User Programs and System Calls
Overview
n Objective: Allow Pintos to execute user programs.
n Requirements:¨ Implement Argument Passing.
¨ Implement System Callsn Process System Callsn Process System Calls
n File System Calls.
n Does NOT depend on project 1
User vs Kernel Code
n OLD:
¨ run_test ran code directly in the main thread of kernel.
¨ Test code had full access to privileged parts of the system.
NEW:n NEW:
¨ Tests in src/userprog/ are now user code
¨ process_execute("cp -r pintos .")
¨ calls create_thread(...)
¨ calls execute_thread(...)
¨ Runs “cp” in user space.
User vs Kernel Code
n Our user programs have some limitations¨ no dynamic memory allocation,
¨ no threading within user code
¨ no floating point operations
n src/examples directory contains a few sample user programs. programs.
n Pintos can load ELF executables with the loader provided in userprog/process.c.
n Need to copy user executables into virtual disk. (More on this later)
User vs Kernel Memory
n Virtual memory in Pintos is divided into two regions: user virtual memory and kernel virtual memory.
n User Virtual Memory:
¨ It is per process.
¨ On process context switch, kernel also switches user virtual address spaces.
¨ processor's page directory base register points to current process page directory.current process page directory.
¨ Struct thread contains pointer to page directory.
¨ IMPORTANT: Not all pages in User virtual Memory are mapped to actual physical memory.
n Kernel Virtual Memory:
¨ Global. Always mapped the same way regardless of process.
¨ In Pintos, kernel virtual memory is mapped one-to-one to physical memory, starting at PHYS_BASE.
User vs Kernel Memory
n User code can not access addresses above PHYS_BASE.
n The user can only access mapped addresses in its page tables.
n If the user tries to access an unmapped address, it will page faultaddress, it will page fault
n Even in kernel mode you can page fault if you try to access an unmapped user address
n If interested, useful sections in Reference Guide related to memory management.¨ A.5 (Memory Allocation)
¨ A.6 (Virtual Addresses)
¨ A.7 (Page Table)
Enabling User Code
n Start it running
¨ Set up the stack
n Allow it to do things (System Calls)
¨ Interact with the file systemInteract with the file system
¨ Interact with the user
¨ Communicate with other processes
n Don’t let it crash the kernel!
¨ Check all user pointers
Setting up the stack
In the Pintos C library the entry point for a user Program is the _start function call defined in lib/user/entry.c
void_start (int argc, char *argv[]){exit (main (argc, argv));}
• You must set up the call to _start by hand. This should be done in setup_stack() function in process.c.
Return Address
System Calls
n System Calls are Internal Interrupts generated by the user program.
n Used to request a privileged operation from operating system¨ E.g. open a new file.¨ E.g. open a new file.
n In Pintos, user programs invoke "int $0x30" to make a system call
n The system call number and any arguments are pushed on the user stack in before invoking the interrupt.
Handling System Calls
n Get user stack pointer from “esp” member of struct intr_frame passed to syscall_handler (struct intr_frame).
n The system call number is the first 32-bit number on the user stack.
¨ Match these with the system call types defined in lib/syscall-nr.h to find what system call was made.
n Syscall arguments are next 32-bit words higher up.
¨ E.g. if wait(pid) system call is made the pid will be the next 32-bit word after the system call number.
¨ Other arguments (upto 3) will follow.
n Return the result of the system call in the “eax” member of struct intr_frame.
¨ On return from system call this will be restored to actual eax register.
System Calls - Filesystemn You do NOT need to change the file system for this project
n Users deal with file descriptors (ints). The file system uses struct file *. You need to enforce a mapping.
n The file system is not thread-safe (yet!) so use coarse synchronization to protect it.
n File system calls to be implemented for this project.¨ bool create (const char *file, unsigned initial_size);
¨ bool remove (const char *file);
¨ int open (const char *file);
¨ int filesize (int fd);
¨ int read (int fd, void *buffer, unsigned length);
¨ int write (int fd, const void *buffer, unsigned length);
¨ void seek (int fd, unsigned position);
¨ unsigned tell (int fd);
¨ void close (int fd);
System Calls - Filesystem
n Reading from the keyboard and writing to the console are special cases
n fd STDOUT_FILENO
¨ Can use putbuf(…) or putchar(…)
¨ In src/lib/kernel/console.c¨ In src/lib/kernel/console.c
n fd STDIN_FILENO¨ Can use input_getc (…)
¨ In src/devices/input.h
System Calls - Processes
n int wait (pid_t pid)¨ Parent must block until the child process pid exits
¨ Must return the status value of the child
¨ Must work if child has already exited
¨ Must fail if it has already been called on the child.
n void exit (int status)¨ Exit w/ the specified status & free resources
¨ Required: print out the exit status
¨ Need synchronization with wait so the parent can retrieve your status if desired.
System Calls - Processes
n pid_t exec (const char *cmd_line)¨ Create a new child process
¨ This MUST not return until the new process has successfully been created (or has failed)
n Design these three well! They are the most time consuming.
System Calls – Important Checks
n In a system call, the user will pass you all kinds of addresses (buffers, strings, stack pointers, etc).
n Trust no one. Check anything the user passes to you.
¨ Is the passed-in address in user memory?
¨ You can use pagedir_get_page(…) to check if the address is ¨ You can use pagedir_get_page(…) to check if the address is mapped for the user program.
n Kill the process if it passes an illegal address.¨ Free any locks and resources.
n After this project your Pintos implementation should be bullet-proof.
¨ No user program should be able to crash system.
Utilities – Making Disks
n User code must be on a virtual hard drive¨ cd pintos/src/userprog
¨ make
¨ pintos-mkdisk fs.dsk 2 /*create a 2MB disk*/
¨ pintos -f -q /*format the disk*/
¨ pintos -p ../examples/echo -a echo -- -q /*put a program on the disk
and rename it*/and rename it*/
¨ pintos -q run 'echo x' /* run the program*/
n Recommend making a backup disk w/ programs loaded in case your disk gets trashed.
n Also can create temporary disks and load programs on the fly.
¨ pintos --fs-disk=2 -p ../../examples/echo -a echo -- -f -q run 'echo x'
Getting Started
n Make a disk and add some simple programs¨ run make in src/examples
n Temporarily set up the stack to avoid page faulting immediately. esp = esp - 12;
n Enable reading from user memory addresses
n Handle write( ) syscall for STDOUT_FILENO
n Change process_wait to an infinite loop so that pintos doesn’t power off
Utilities – Debugging User Programs
n Start pintos-gdb as usual¨ add-symbol-file program
n Set breakpoints, etc, in user code
¨ Kernel names will take precedence over user code
¨ Change this by doing pintos-gdb userprog.o, then add-symbol-file ¨ Change this by doing pintos-gdb userprog.o, then add-symbol-file kernel.o
Questions?