Processes
Mode Transfer Review & Wrap up
- putting it all together: detailed control flow for all mode transfers
- switch to kernel mode, save process's program counter & stack, switch to kernel stack, set PC to a kernel handler function
- kernel handler first pushes the rest of process's states (registers) onto the kernel stack
- kernel handler executes the rest of the logic, handles the specific syscall, exception, or interrupt
- restores the process's states (pop off the stack)
- returns back to user mode, restores saved PC and stack pointer, resumes execution
- resumes at next instruction for syscalls
- resumes at interrupted instruction for interrupts
- how does the first process start executing in user mode?
- system call validation
Process Abstraction
- a running instance of a program
- isolation and protection boundary for user programs
- a process's failure shouldn't affect other processes
- a process shouldn't have visibility into other processes
- unless explicitly permitted by other processes or through OS APIs (e.g. fork)
- a process consists of
- execution stream (thread): abstraction of CPU
- includes execution/CPU states (instruction pointer, stack pointer, other registers)
- virtual address space: abstraction of physical memory
- includes code, data, stack, and heap regions
- client data from using other OS abstractions: file system, networks, inter-process communication
- open files, sockets, pipes
Process Implementation
- how does a program become a process?
- ELF loading: execution states & address space setup
- how do processes share a CPU
- scheduling: processes take turn running on the CPU
- who gets to run is determined by the OS scheduling policy
- process life cycle
- dispatch: it's the process's turn to run on the CPU now!
- timeout: time is up, have to give up the CPU
- blocking: waiting on some event to happen, have no use for the CPU for now
- unblocking: the event the process was waiting on happened, ready to use the CPU again
- where do we track all the information about a process?
- Process Control Block (PCB)
- kernel metadata of a process
- states include pid, scheduling state, trapframe, address space info
- includes client data of other OS abstractions (e.g. open files)
Process APIs
- fork
- creates a new process that is the exact copy of the calling process
- child's virtual address space is identical to the parent at the time of fork
- after fork, updates to parent's or child's address space is only visible to that process
- separate physical memory, separate memory translation table
- child's execution states (registers, pc, sp) are the same as parent's
- where does the child start executing?
- how do we know which one is parent which one is child?
- diffferent
%rax
, parent gets the child's pid, child gets a 0
- child inherits parent's OS resources (e.g. same set of open files)
- easy way for parent to configure the child's OS resources
- exec
- loads a new program into the current process
- replace the address space and execution states of the current process
- new code, data, heap, and stack region
- takes a list of string arguments to pass in as the new program's command line args
- process's view:
int main(int argc, char** argv)
- argv[0] = program name, argv[1..] = command line arg pointers
- OS sets up the users's stack with the command line args and the argv array (null terminated)
- execution states change as a result (new PC & SP)
- does NOT create a new process, process looks different but has the same pid and OS resources
- often used in combination with fork to create a new process and executes a new program
- shell uses fork + exec to implement redirect, how?
- fork/exec combo
- simple semantics: separate process creation from program loading
- any cost to this combo?
- what happens to the forked memory upon an exec?
- can we do better? copy-on-write (COW) fork!
- instead of copying all of parent's memory upon fork, share the same memory as the parent for as long as possible
- as long as both parent and child are only doing reads it's safe to share
- upon a write, makes a separate copy of memory so that parent/child can perform independent writes
- how do we tell if a write happens?
- is fork really a simple semantic?
- exit
- terminate the current process, does not return!
- clean up OS resources it's using
- open files should be closed, virtual address space deallocated
- what about its kernel stack? can a process free its own kernel stack?
- wait
- wait for a child process to exit
- what happens if no child has exited when the parent has called wait?
- what happens if a child already exited before the parent has called wait?
- can the parent wait on the same child twice?
- kernel needs to track the parent child relationship
- parent responsible for cleaning up the rest of child's resources
- what if parent exits without waiting on its children?