Recitation 8 (Nov. 1) Outline TA: Kun Gao Lab 5 hints Virtual Memory Reminder Shell Lab: Due THIS Thursday Modified from Minglong Shao’s Recitation, Fall 2004 Lab 5 A tiny shell (tsh) with job control & I/O redirection Key points: Understand process tree Executing programs Reap all child processes Handle SIGCHLD, SIGTSTP, SIGINT Avoid race hazard I/O redirection Process tree for shell pid=10 pgid=10 Shell Background job #1 pid=20 Forepgid=20 ground job pid=32 pgid=32 Background process group 32 Child pid=21 pgid=20 Child pid=22 pgid=20 Foreground process group 20 Background job #2 pid=40 pgid=40 Backgroud process group 40 Each job has a unique process group id int setpgid(pid_t pid, pid_t pgid); setpgid(0, 0); Process tree for shell (part 2) pid=5 pgid=5 pid=10 pgid=10 UNIX shell tsh Background job #1 pid=20 Forepgid=20 ground job Foreground job receives SIGINT, SIGTSTP, when you type ctrl-c, ctrl-z pid=32 pgid=32 Background process group 32 Child pid=21 pgid=20 Child pid=22 pgid=20 Foreground process group 20 Background job #2 pid=40 pgid=40 Backgroud process group 40 int kill(pid_t pid, int sig) pid > 0: send sig to specified process pid = 0: send sig to all processes in same group pid < -1: send sig to group -pid Execute program int execve(const char *fname, char *const argv[], char *const envp[]); Examples: execve(“/bin/ls”, NULL, NULL); execve(“./mytest”, argv, envp); Reaping child process waitpid(pid_t pid, int *status, int options) pid: wait for child process with pid (process id or group id) -1: wait for any child process status: tell why child terminated options: WNOHANG: return immediately if no children zombied WUNTRACED: report status of terminated or stopped children In Lab 5, use waitpid(-1, &status, WNOHANG|WUNTRACED) In sigchld_handler(): while ((c_pid = waitpid(…)) > 0) { … } Reaping child process (part 2) int status; waitpid(pid, &status, WNOHANG|WUNTRACED) What to check in sigchld_handler: WIFEXITED(status): child exited normally (the child finished, and quit normally on its own) WEXITSTATUS(status): returns code when child exits WIFSIGNALED(status): child exited because a signal is not caught (SIGINT, or typing CTRL-C) WTERMSIG(status): gives the terminating signal number WIFSTOPPED(status): child is stopped by the receipt of a signal (SIGSTOP, or typing CTRL-Z) WSTOPSIG(status): gives the stop signal number Reaping child process (part 3) Where to put waitpid(…) In sigchld_handler(): for both tsh should still wait for fg job to complete, how? Busy wait for foreground job In eval(): if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ /* do nothing */ } } Sleep In eval(): if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ sleep(1); } } Race hazard A data structure is shared by two pieces of code that can run concurrently Different behaviors of program depending upon how the schedule interleaves the execution of code. An example of race hazard sigchld_handler() { while ((pid = waitpid(…)) > 0){ deletejob(pid); } } eval() { pid = fork(); if(pid == 0) { /* child */ execve(…); } /* parent */ /* signal handler may run BEFORE addjob()*/ addjob(…); } An okay schedule time Shell Signal Handler Child fork() addjob() execve() exit() sigchld_handler() deletejobs() A problematic schedule time Shell Signal Handler Child fork() execve() exit() sigchld_handler() deletejobs() addjob() Job added to job list after the signal handler tried to delete it! Solution: blocking signals sigchld_handler() { pid = waitpid(…); deletejob(pid); } eval() { sigprocmask(SIG_BLOCK, …) pid = fork(); if(pid == 0) { /* child */ sigprocmask(SIG_UNBLOCK, …) execve(…); } /* parent */ /* signal handler might run BEFORE addjob() */ addjob(…); sigprocmask(SIG_UNBLOCK, …) } Solution: blocking signals (part 2) What should our block set be? SIGSTP SIGINT SIGCHLD I/O redirection Do it before call execve() in child process eval() { pid = fork(); if(pid == 0) { /* child */ /* Redirect I/O */ if (redirect_input) dup2(…);/* redirect STDIN */ if (redirect_output) dup2(…);/* redirect STDOUT */ execve(…); } addjob(…); } dup2(int oldfd, int newfd) Covered in Chapter 11 oldfd: old file descriptor newfd: new file descriptor Dup2 makes newfd be a copy of the oldfd (i.e. operations on newfd is done on oldfd instead) Some examples: Get input from in_fd instead of standard input dup2(in_fd, STDIN_FILENO); Print output to out_fd instead of standard output dup2(out_fd, STDOUT_FILENO); Reminders Some important system calls: fork(), execve(), waitpid(), sigprocmask(), setpgid(), kill() … Check man pages for details about system calls man 2 kill Check return values of all system calls STEP by STEP Test your shell by typing commands first Each trace worth the same (work on easy ones first!) Start now! Virtual memory One of the most important concepts in CS Why use virtual memory (VM) Use RAM as a cache for disk Easier memory management Access protection Enable “partial swapping” Share memory efficiently Virtual memory Memory Per Process: 0: 1: Page Table Virtual Addresses 0: 1: Physical Addresses CPU P-1: N-1: Page Page table Page hits, Page faults Demand Paging Disk Conceptual address translation Higher bits of address (page number) mapped from virtual addr. to physical addr. Lower bits (page offset) stay the same. p p–1 n–1 virtual page number (VPN) page offset 0 virtual address address translation m–1 p p–1 physical page number (PPN) 0 page offset Virtual Memory: up to 2n -1 bytes Physical Memory: up to 2m -1 bytes physical address Address translation through page table Translation Separate (set of) page table(s) per process VPN forms index into page table (points to a page table entry) page table base register VPN acts as table index if valid=0 then page not in memory virtual address n–1 p p–1 virtual page number (VPN) page offset 0 valid access physical page number (PPN) m–1 p p–1 physical page number (PPN) page offset physical address 0 Address translation with TLB n–1 p p–1 0 virtual page number page offset valid . virtual address tag physical page number . TLB . = TLB hit physical address tag index valid tag byte offset data Cache = cache hit data Integrating VM and cache Most caches are physically addressed Why? Perform address translation before cache lookup, could potentially go to memory =*( TLB keeps things manageable 1. VA CPU 4. PA MMU/ Translation 2. VPN 3. PTE TLB 5. Data Cache/Memory Integrating VM and cache (TLB hit) Most caches are physically addressed Why? Perform address translation before cache lookup, could potentially go to memory =*( TLB keeps things manageable 1. VA CPU 4. PA MMU/ Translation 2. VPN 3. PTE TLB 5. Data Cache/Memory Integrating VM and cache (TLB miss) TLB miss, but page table is in cache/memory 3. PTEA (PTBP + VPN) 1. VA CPU MMU/ Translation 2. VPN TLB 6. Data 5. PA 4. PTE Cache/Memory What is the worst case mem read (most delay)? TLB miss, page fault on page table, then page fault on memory read 3. PTEA (PTBP + VPN) 1. VA CPU MMU/ Translation 2. VPN 5. PA 4. PTE Cache/Memory TLB Page Fault/ Page Fault/ Page Table Mem Read 6. Data DISK Example Understand end-to-end addr. translation 20-bit virtual addresses 18-bit physical addresses Page size is 1024 bytes TLB is 2-way associative with 16 total entries Part 1 A. Virtual address TLBT 19 18 17 16 TLBI 15 14 13 12 11 10 9 8 7 6 VPN 5 4 3 2 1 0 3 2 1 0 VPO B. Physical address 17 16 15 14 13 PPN 12 11 10 9 8 7 6 5 4 PPO Example: TLB and page table Part 2 Virtual address 0x04AA4 A. 04AA4 = 0000 0100 1010 1010 0100 B. Address translation parameter VPN Value 0x012 Parameter TLB hit? Value Y TLB Index TLB Tag 0x2 0x02 Page fault? PPN N 0x68 C. Physical address 01 1010 0010 1010 0100 Part 2 Virtual address 0x78E6 A. 078E6 = 0000 0111 1000 1110 0110 B. Address translation parameter VPN Value 0x01E Parameter TLB hit? Value N TLB Index TLB Tag 0x6 0x03 Page fault? PPN N 0x57 C. Physical address 01 0101 1100 1110 0110 End-to-end address translation Section 10.6.4: a concrete example Read carefully and solve practice problem 10.4