Class 2 CS 439 17 January 2013 On the board ------------ http://www.cs.utexas.edu/~mwalfish/classes/s13-cs439 1. Last time 2. Privileged vs. unprivileged mode 3. Processes 4. Context switches --------------------------------------------------------------------------- 1. Last time --course intro --what is an OS? why study? how will we study? --course mechanics --examples and history 2. Privileged vs. unprivileged mode --the difference between these modes is something that the *hardware* understands and enforces --the OS runs in privileged mode --can mess with the hardware --can manipulate OS abstractions (obviously, but worth repeating) --users' tasks run in unprivileged mode --cannot mess with the hardware --sees a picture of a virtual machine --the hardware knows the difference between privileged and unprivileged mode (on the x86, these are called ring 0 and ring 3. The middle rings aren't used in the classical setup, but they are used in some approaches to virtualization.) --TRANSITION: what do we mean by users' tasks? 3. Processes write on the board ------------------ * what is the point? * what is a process? * how do they interact with the operating system? * how do they come into being? --whole point to processes is to share the resources of the machine (one waits for the input, and the other can do stuff.) --while giving each task the illusion that it has access to a full machine PICTURE: loader HUMAN --> SOURCE CODE --> EXECUTABLE -----------> PROCESS vi gcc as ld loader HUMAN ---> foo.c ---> foo.s ----> foo.o ---> a.out ----> process NOTE: 'ld' is the name of the linker. it stands for 'linkage editor'. [you will build a primitive loader in labs 5,6] A. What is a process? --instance of a running program --browser, text editor, etc. --the program sees an abstraction of a virtual machine (virtual memory, virtual CPU, etc.). [draw picture] --here's an implementation: PCB ----------------- | process id | | state | (ready, runnable, blocked, etc.) | user id | | IP | | open file | | VM structures | | registers | | ..... | (signal mask, terminal, priority, ...) ---------------- called "proc" in Unix, "task_struct" in Linux, and "struct env" in JOS --each one has its own view of virtual memory, which contains: --program code (aka "text") --constants --zeroed-out area for variables --stack --heap --its own registers --state of OS resources --very little else is actually needed, but a modern process does have a lot of associated information: --signal state --UID, signal mask, controlling terminal, priority, whether being debugged, etc., etc. --typically has less privilege than operating system --OS can manipulate the hardware. processes cannot. (see above, regarding privileged v. unprivileged mode) --OS (obviously) can manipulate OS abstractions. processes cannot. B. How do processes interact with the operating system? --syscalls, or system calls: the interface to the operating system. (API exposed by the kernel to user programs) --that is, **syscalls are how user-level programs ask the operating system to do things for them ** --lots of system calls --on Unix, type "man 2 " to get documentation. --here are three relevant ones on Unix: int fd = open(const char* path, int flags) write(fd, const void *, size_t) read(fd, void *, size_t) --fd is a *file descriptor*. this is an abstraction, provided by the operating system, that represents an open file --every process can usually expect to begin life with three file descriptors already open: 0: represents the input to the process (e.g., tied to terminal) 1: represents the output 2: represents the error output these are sometimes known as stdin, stdout, stderr --NOTE: Unix hides for processes the difference between a device and a file. this is a very powerful hiding (or abstraction), as we will see soon --here are some other system calls (these are included in the notes so that you know what the basic interface to a Unix-like OS looks like): --int open(char*, int flags, [, int mode]); --int read(int fd, void*, int nbytes): --int write(int fd, void* buf, int nbytes); --off_t lseek(int fd, off_t pos, int whence) --int close(int fd); --int kill(int pid, int signal) --void exit (int status) --int fork(void) --int waitpid(int pid, int* stat, int opt) --int execve(char* prog, char** argv, char** envp) --int dup2 (int oldfd, int newfd) --int pipe(int fds[2]) --when a user-level program invokes the kernel via a syscall, it is called *trapping* to the kernel app | (open) v --------------------------- ^ | | |____> [table] open() | ..... | return -------- C. How does a process come into being? --answer: another system call! --in Unix, it is fork() --on JOS, it is exo_fork() --fork() creates an exact copy (almost; the return value is different). --thus, what happens if a system had two important users, and one of them runs a process that executes this code: for (i = 0; i < 10; i++) { fork(); } while (1) {} [answer: one of the users gets a LOT more of the CPU than another] --what behavior do you want? [this actually corresponds to research. OSes are only just applying resource containers.] --------------------------------------------------------------------------- Admin: --class Web site --discussion leaders posted --lab and homework due on Tuesday --------------------------------------------------------------------------- 4. Context switches Question: When does the kernel switch which process or thread is running? (This is called a context switch.) Answer: under three scenarios: --interrupt (from device or timer) the "device" case: new data arrives from the network or the disk. interrupts operating system to let it know that it can run a different process. the "timer" case: by timer, we mean the following..... the behavior that we want is: each process that is running gets a fixed amount of time to run without interruption; this amount of time is called a quantum; if a process uses up its quantum, another one is scheduled. the way that the OS achieves this behavior is that there's a hardware device that regularly interrupts the operating system, giving it the opportunity to change which process is running. --traps (running process performs a system call). reason: syscall by one process can result in that process being put to sleep (e.g., if it does a read from the disk) or some other process becoming runnable (e.g., if it wakes up another process with an inter-process message) confusingly, the 'int' instruction on the x86 generates traps --exception --divide by 0 --page fault --.... Question: How does the kernel switch which process is running? (This is called a context switch.) Answer: the kernel implements it, at a high level, by saving the IP, registers, and VM translations of the running process ... and reloading another process's state --how do we implement context switches? --[draw picture] --save IP and registers --change VM translations --context switches can be expensive