1 / 58

CS: Chapter 7 Exceptional Control Flow

CS: Chapter 7 Exceptional Control Flow. SW Project II: Advanced Linux Programming M ulti- M edia S ystems Engineering Dept. Byoung-Jo CHOI 2007 Fall.

said
Download Presentation

CS: Chapter 7 Exceptional Control Flow

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS: Chapter 7Exceptional Control Flow SW Project II: Advanced Linux Programming Multi-Media Systems Engineering Dept. Byoung-Jo CHOI 2007 Fall This lecture material is based on the slides and the textbook, "Computer Systems: A Programmer's Perspective" by R.E.Bryant and D.R.O'Hallaron at Carnegie Melon University.

  2. Chapter Overview Exceptions Processes Systems Calls and Error Handling Process Control Signals

  3. Control Flow • Computers do Only One Thing • From startup to shutdown, a CPU simply reads and executes (interprets) a sequence of instructions, one at a time. • This sequence is the system’s physical control flow (or flow of control). Physical control flow <startup> inst1 inst2 inst3 … instn <shutdown> Time

  4. Altering the Control Flow • Up to now: two mechanisms for changing control flow: • Jumps and branches • Call and return using the stack discipline. Both react to changes in program state. • Insufficient for a useful system • Difficult for the CPU to react to changes in system state. • data arrives from a disk or a network adapter. • Instruction divides by zero • User hits ctl-c at the keyboard • System timer expires • System needs mechanisms for “exceptional control flow” (ECF)

  5. ECF Exists at All Levels of a System • Exceptions • Hardware and operating system kernel code • Concurrent processes • Hardware timer and operating system kernel code • Signals • Operating system kernel code • Non-local jumps • Application code Lower levels Higher levels

  6. System Context for Exceptions USB Ports Keyboard Mouse Modem Printer Processor Interrupt controller Timer Serial port controllers Parallel port controller Super I/O Chip Local/IO Bus Video adapter Network adapter Memory IDE disk controller SCSI controller SCSI bus disk Network Display disk CDROM

  7. Exceptions • An exception is a transfer of control to the OS in response to some event (i.e., change in processor state) User Process OS exception current event next exception processing by exception handler exception return (optional)

  8. Interrupt Vectors • Each type of event has a unique exception number k • Index into jump table (a.k.a., interrupt vector) • Jump table entry k points to a function (exception handler). • Handler k is called each time exception k occurs. Exception numbers code for exception handler 0 interrupt vector code for exception handler 1 0 1 code for exception handler 2 2 ... ... n-1 code for exception handler n-1

  9. Asynchronous Exceptions (Interrupts) • Caused by events external to the processor • Indicated by setting the processor’s interrupt pin • handler returns to “next” instruction. • Examples: • I/O interrupts • hitting ctl-c at the keyboard • arrival of a packet from a network • arrival of a data sector from a disk • Hard reset interrupt • hitting the reset button • Soft reset interrupt • hitting ctl-alt-delete on a PC

  10. Synchronous Exceptions • Caused by events that occur as a result of executing an instruction: • Traps • Intentional • Examples: system calls, breakpoint traps, special instructions • Returns control to “next” instruction • Faults • Unintentional but possibly recoverable • Examples: page faults (recoverable), protection faults (unrecoverable), floating point exceptions. • Either re-executes faulting (“current”) instruction or aborts. • Aborts • unintentional and unrecoverable • Examples: parity error, machine check. • Aborts current program

  11. Trap Example • Opening a File • User calls open(filename, options) • Function open executes system call instruction int • OS must find or create file, get it ready for reading or writing • Returns integer file descriptor 0804d070 <__libc_open>: . . . 804d082: cd 80 int $0x80 804d084: 5b pop %ebx . . . User Process OS exception int pop Open file return

  12. User Process OS page fault event movl Create page and load into memory return Fault Example #1 int a[1000]; main () { a[500] = 13; } • Memory Reference • User writes to memory location • That portion (page) of user’s memory is currently on disk • Page handler must load page into physical memory • Returns to faulting instruction • Successful on second try 80483b7: c7 05 10 9d 04 08 0d movl $0xd,0x8049d10

  13. User Process OS or Hardware TLB miss event movl Look up address translation and store it in a TLB entry return Fault Example #2 int a[1000]; main () { a[500] = 13; } • Memory Reference with TLB miss • User writes to memory location • That portion (page) of user’s memory is currently in physical memory, but the processor has forgotten how to translate this virtual address to the physical address • TLB must be reloaded with current translation • Returns to faulting instruction • Successful on second try

  14. Fault Example #3 int a[1000]; main () { a[5000] = 13; } • Memory Reference • User writes to memory location • Address is not valid • Page handler detects invalid address • Sends SIGSEGV signal to user process • User process exits with “segmentation fault” 80483b7: c7 05 60 e3 04 08 0d movl $0xd,0x804e360 User Process OS page fault event movl Detect invalid address Send SIGSEGV signal to process

  15. Processes • Definition: A process is an instance of a running program. • One of the most profound ideas in computer science. • Not the same as “program” or “processor” • Process provides each program with two key abstractions: • Logical control flow • Each program seems to have exclusive use of the CPU. • Private address space • Each program seems to have exclusive use of main memory. • How are these Illusions maintained? • Process executions interleaved (multitasking) • Address spaces managed by virtual memory system

  16. The World of Multitasking • System Runs Many Processes Concurrently • Process: executing program • State consists of memory image + register values + program counter • Continually switches from one process to another • Suspend process when it needs I/O resource or timer event occurs • Resume process when I/O available or given scheduling priority • Appears to user(s) as if all processes executing simultaneously • Even though most systems can only execute one process at a time • Except possibly with lower performance than if running alone

  17. Logical Control Flows Each process has its own logical control flow Process A Process B Process C Time

  18. Process A Process B Process C Time Concurrent Processes • Two processes run concurrently (are concurrent) if their flows overlap in time. • Otherwise, they are sequential. • Examples: • Concurrent: A & B, A & C • Sequential: B & C

  19. User View of Concurrent Processes • Control flows for concurrent processes are physically disjoint in time. • However, we can think of concurrent processes are running in parallel with each other. Process A Process B Process C Time

  20. Context Switching • Processes are managed by a shared chunk of OS code called the kernel • Important: the kernel is not a separate process, but rather runs as part of some user process • Control flow passes from one process to another via a context switch. Process A code Process B code user code context switch kernel code Time user code context switch kernel code user code

  21. Private Address Spaces • Each process has its own private address space. 0xffffffff kernel virtual memory (code, data, heap, stack) memory invisible to user code 0xc0000000 user stack (created at runtime) %esp (stack pointer) memory mapped region for shared libraries 0x40000000 brk run-time heap (managed by malloc) read/write segment (.data, .bss) loaded from the executable file read-only segment (.init, .text, .rodata) 0x08048000 unused 0

  22. fork: Creating New Processes • int fork(void) • creates a new process (child process) that is identical to the calling process (parent process) • returns 0 to the child process • returns child’s pid to the parent process if (fork() == 0) { printf("hello from child\n"); } else { printf("hello from parent\n"); } Fork is interesting (and often confusing) because it is called once but returns twice

  23. fork Example #1 • Key Points • Parent and child both run same code • Distinguish parent from child by return value from fork • Start with same state, but each has private copy • Including shared output file descriptor • Relative ordering of their print statements undefined void fork1() { int x = 1; pid_t pid = fork(); if (pid == 0) { printf("Child: x=%d\n",++x); } else { printf("Parent: x=%d\n",--x); } printf("Bye from %d with x = %d\n", getpid(), x); } Child:x=2, Bye… x=2 Parent:x=0, Bye… x=0

  24. Bye L1 Bye Bye L0 L1 Bye fork Example #2 • Key Points • Both parent and child can continue forking void fork2() { printf("L0\n"); fork(); printf("L1\n"); fork(); printf("Bye\n"); }

  25. exit: Destroying Processes • void exit(int status) • exits a process • Normally return with status 0 • atexit() registers functions to be executed upon exit void cleanup(void) { printf("cleaning up\n"); } void fork6() { atexit(cleanup); fork(); exit(0); }

  26. Zombies • Idea • When process terminates, still consumes system resources • Various tables maintained by OS • Called a “zombie” • Living corpse, half alive and half dead • Reaping • Performed by parent by “waiting” on terminated child • Parent is given exit status information • Kernel discards process • What if Parent Doesn’t Reap? • If any parent terminates without reaping a child, then child will be reaped by init process (parent of all processes) • Only need explicit reaping for long-running processes • E.g., shells and servers

  27. Wait: Synchronizing with and Reaping Children • int wait(int *child_status) • Suspends current process until one of its children, p, terminates • Return value is the pid of process p • Returning from wait reaps process p • If child_status!= NULL, then the object it points to will be set to a status indicating why process p terminated

  28. HC Bye HP CT Bye Wait Example void fork9() { int child_status; if (fork() == 0) { printf("HC: hello from child\n"); } else { printf("HP: hello from parent\n"); wait(&child_status); printf("CT: child has terminated\n"); } printf("Bye\n"); exit(); }

  29. Waiting for Multiple Children • If multiple children completed, will take in arbitrary order • Can use macros WIFEXITED and WEXITSTATUS to get information about exit status void fork10() { pid_t pid[N]; int i, child_status; for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) exit(100+i); /* Child */ for (i = 0; i < N; i++) { pid_t wpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminate abnormally\n", wpid); } }

  30. waitpid: Waiting for a Specific Child • waitpid(pid, &status, options) • Can wait for specific process • Various options (see CS:APP) void fork11() { pid_t pid[N]; int I, child_status; for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) exit(100+i); /* Child */ for (i = 0; i < N; i++) { pid_t wpid = waitpid(pid[i], &child_status, 0); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminated abnormally\n", wpid); }

  31. exec: Running New Programs • int execl(char *path, char *arg0, char *arg1, …, 0) • Family of functions wrapped around execv • Loads and runs executable at path with args arg0, arg1, … • path is the complete path of an executable • arg0 becomes the name of the process • typically arg0 is either identical to path, or else it contains only the executable filename from path • “real” arguments to the executable start with arg1, etc. • list of args is terminated by a (char *)0 argument • Returns -1 if error, otherwise doesn’t return! main() { if (fork() == 0) { execl("/usr/bin/cp", "cp", "foo", "bar", 0); } wait(NULL); printf("copy completed\n"); exit(); }

  32. Exec Example • Typically used in conjunction with fork. main() { if (fork() == 0) { execl("/usr/bin/cp", "cp", "foo", "bar", 0); } wait(NULL); printf("copy completed\n"); exit(); }

  33. Summary of Process Control • Spawning Processes • Call to fork • One call, two returns • Terminating Processes • Call exit • One call, no return • Reaping Processes • Call wait or waitpid • Replacing Program Executed by Process • Call execl (or variant) • One call, (normally) no return

  34. Linux Process Hierarchy [0] init [1] Daemon e.g. httpd Login shell Child Child Child Grandchild Grandchild

  35. Unix Startup: Step 1 1. Pushing reset button loads the PC with the address of a small bootstrap program. 2. Bootstrap program loads the boot block (disk block 0). 3. Boot block program loads kernel binary (e.g., /boot/vmlinux) 4. Boot block program passes control to kernel. 5. Kernel handcrafts the data structures for process 0. [0] Process 0: handcrafted kernel process Process 0 forks child process 1 init [1] Child process 1 execs /sbin/init

  36. Unix Startup: Step 2 [0] init [1] /etc/inittab init forks and execs daemons per /etc/inittab, and forks and execs a getty program for the console Daemons e.g. ftpd, httpd getty

  37. Unix Startup: Step 3 [0] init [1] The getty process execs a login program login

  38. Unix Startup: Step 4 [0] init [1] login reads login-ID and passwd. if OK, it execs a shell. if not OK, it execs another getty tcsh In case of login on the console xinit may be used instead of a shell to start the window manger

  39. Shell Programs • A shell is an application program that runs programs on behalf of the user. • sh – Original Unix Bourne Shell • csh – BSD Unix C Shell, tcsh – Enhanced C Shell • bash –Bourne-Again Shell (Linux version of sh) int main() { char cmdline[MAXLINE]; while (1) { /* read */ printf("> "); Fgets(cmdline, MAXLINE, stdin); if (feof(stdin)) exit(0); /* evaluate */ eval(cmdline); } } • Execution is a sequence of read/evaluate steps

  40. void eval(char *cmdline) { char *argv[MAXARGS]; /* argv for execve() */ int bg; /* should the job run in bg or fg? */ pid_t pid; /* process id */ bg = parseline(cmdline, argv); if (!builtin_command(argv)) { if ((pid = Fork()) == 0) { /* child runs user job */ if (execve(argv[0], argv, environ) < 0) { printf("%s: Command not found.\n", argv[0]); exit(0); } } if (!bg) { /* parent waits for fg job to terminate */ int status; if (waitpid(pid, &status, 0) < 0) unix_error("waitfg: waitpid error"); } else /* otherwise, don’t wait for bg job */ printf("%d %s", pid, cmdline); } } Simple Shell eval Function

  41. Problem with Simple Shell Example • Shell correctly waits for and reaps foreground jobs. • But what about background jobs? • Will become zombies when they terminate. • Will never be reaped because shell (typically) will not terminate. • Creates a memory leak that will eventually crash the kernel when it runs out of memory. • Solution: Reaping background jobs requires a mechanism called a signal.

  42. Signals • A signal is a small message that notifies a process that an event of some type has occurred in the system. • Kernel abstraction for exceptions and interrupts. • Sent from the kernel (sometimes at the request of another process) to a process. • Different signals are identified by small integer ID’s (1-30) • The only information in a signal is its ID and the fact that it arrived. man 7 signal

  43. Signal Concepts • Sending a signal • Kernel sends (delivers) a signal to a destination process by updating some state in the context of the destination process. • Kernel sends a signal for one of the following reasons: • Kernel has detected a system event such as divide-by-zero (SIGFPE) or the termination of a child process (SIGCHLD) • Another process has invoked the kill system call to explicitly request the kernel to send a signal to the destination process.

  44. Signal Concepts (continued) • Receiving a signal • A destination process receives a signal when it is forced by the kernel to react in some way to the delivery of the signal. • Three possible ways to react: • Ignore the signal (do nothing) • Terminate the process (with optional core dump). • Catch the signal by executing a user-level function called a signal handler. • Akin to a hardware exception handler being called in response to an asynchronous interrupt.

  45. Signal Concepts (continued) • A signal is pending if it has been sent but not yet received. • There can be at most one pending signal of any particular type. • Important: Signals are not queued • If a process has a pending signal of type k, then subsequent signals of type k that are sent to that process are discarded. • A process can block the receipt of certain signals. • Blocked signals can be delivered, but will not be received until the signal is unblocked. • A pending signal is received at most once.

  46. Signal Concepts • Kernel maintains pending and blocked bit vectors in the context of each process. • pending – represents the set of pending signals • Kernel sets bit k in pending whenever a signal of type k is delivered. • Kernel clears bit k in pending whenever a signal of type k is received • blocked – represents the set of blocked signals • Can be set and cleared by the application using the sigprocmask function.

  47. Process Groups • Every process belongs to exactly one process group Shell pid=10 pgid=10 Fore- ground job Back- ground job #1 Back- ground job #2 pid=20 pgid=20 pid=32 pgid=32 pid=40 pgid=40 Background process group 32 Background process group 40 Child Child • getpgrp() – Return process group of current process • setpgid() – Change process group of a process pid=21 pgid=20 pid=22 pgid=20 Foreground process group 20

  48. Sending Signals with kill Program • kill program sends arbitrary signal to a process or process group • Examples • kill –9 24818 • Send SIGKILL to process 24818 • kill –9 –24817 • Send SIGKILL to every process in process group 24817. linux> ./forks 16 linux> Child1: pid=24818 pgrp=24817 Child2: pid=24819 pgrp=24817 linux> ps PID TTY TIME CMD 24788 pts/2 00:00:00 tcsh 24818 pts/2 00:00:02 forks 24819 pts/2 00:00:02 forks 24820 pts/2 00:00:00 ps linux> kill -9 -24817 linux> ps PID TTY TIME CMD 24788 pts/2 00:00:00 tcsh 24823 pts/2 00:00:00 ps linux>

  49. Sending Signals from the Keyboard • Typing ctrl-c (ctrl-z) sends a SIGINT (SIGTSTP) to every job in the foreground process group. • SIGINT – default action is to terminate each process • SIGTSTP – default action is to stop (suspend) each process Shell pid=10 pgid=10 Fore- ground job Back- ground job #1 Back- ground job #2 pid=20 pgid=20 pid=32 pgid=32 pid=40 pgid=40 Background process group 32 Background process group 40 Child Child pid=21 pgid=20 pid=22 pgid=20 Foreground process group 20

  50. Sending Signals with kill Function void fork12() { pid_t pid[N]; int i, child_status; for (i = 0; i < N; i++) if ((pid[i] = fork()) == 0) while(1); /* Child infinite loop */ /* Parent terminates the child processes */ for (i = 0; i < N; i++) { printf("Killing process %d\n", pid[i]); kill(pid[i], SIGINT); } /* Parent reaps terminated children */ for (i = 0; i < N; i++) { pid_t wpid = wait(&child_status); if (WIFEXITED(child_status)) printf("Child %d terminated with exit status %d\n", wpid, WEXITSTATUS(child_status)); else printf("Child %d terminated abnormally\n", wpid); } }

More Related