Physical Control Flow Physical control flow <startup> inst 1 inst 2 Time inst 3 … inst n <shutdown> Sean Barker 1 Operating System User-level Applications Operating System Hardware Resources Sean Barker 2
Processes Memory Memory Memory Stack Stack Stack Heap Heap Heap … Data Data Data Code Code Code CPU CPU CPU Registers Registers Registers Sean Barker 3 Control Flow Abstraction Process A Process B Process C Time Sean Barker 4
Control Flow Time-Sharing Process A Process B Process C Time Sean Barker 5 Context Switching Process A Process B user code context switch kernel code Time user code context switch kernel code user code Sean Barker 6
Exceptions User-Process OS exception event' exception'processing by/ exception'handler return'or'abort Sean Barker 7 Example: Segmentation Fault int a[1000]; main () { a[5000] = 13; } 80483b7: c7 05 60 e3 04 08 0d movl $0xd,0x804e360 User code Kernel code Excep&on: page fault movl Detect invalid address Signal process Sean Barker 8
Exception Table Excep&on numbers Code for excep&on handler 0 Excep&on Code for Table excep&on handler 1 0 1 Code for 2 excep&on handler 2 ... ... n-1 Code for excep&on handler n-1 Sean Barker 9 Process Management Memory Memory Memory Stack Stack Stack Heap Heap Heap … Data Data Data Code Code Code CPU CPU CPU Registers Registers Registers Sean Barker 10
Fork/Exec Stack 1 Code/state.of.shell.process. Heap Replaced.by.code/state.of.ls. Copy.of.code/state. Data of.shell.process. Code:./usr/bin/bash fork() : child parent child Stack Stack Stack 2 2 3 exec() : Heap Heap Data Data Data Code:./usr/bin/bash Code:./usr/bin/bash Code:./usr/bin/ls Code/state.of.shell.process. 7 Sean Barker 11 Zombies! Sean Barker 12
Reaping: waitpid wait pid_t waitpid(pid_t pid, int* stat, int ops ) Suspend.current.process.(i.e..parent).until.child.with. pid ends. wait set Sean Barker 13 Status Macros wait pid_t waitpid(pid_t pid, int* stat, int ops ) Suspend.current.process.(i.e..parent).until.child.with. pid ends. WEXITSTATUS(stat) child exit code true if terminated normally WIFEXITED(stat) (called exit or returned from main) WIFSIGNALED(stat) true if terminated by signal WIFSTOPPED(stat) true if paused by signal Sean Barker 14
Option Macros wait pid_t waitpid(pid_t pid, int* stat, int ops ) Suspend.current.process.(i.e..parent).until.child.with. pid ends. return immediately if child not WNOHANG already terminated WUNTRACED also wait for paused (stopped) children WCONTINUED also wait for resumed children Sean Barker 15 System Call Error Handling Always check return values! if ((pid = fork()) < 0) { ! fprintf(stderr, "fork error: %s\n", strerror(errno)); ! exit(0); ! } Sean Barker 16
Basic Shell Design others... while (true) { Print command prompt. Read command line from user. Parse command line. If command is built-in, do it. Else fork process to execute command. in child: Execute requested command with execv. (never returns) in parent: Wait for child to complete. } Sean Barker 17 Signals ID Name Corresponding2Event Default2Action Can2 Override? 2 SIGINT Interrupt((Ctrl?C) T erminate Yes 9 SIGKILL Kill(process((immediately) T erminate No 11 SIGSEGV Segmentation(violation T erminate( &(Dump Yes 14 SIGALRM Timer(signal T erminate Yes 15 SIGTERM Kill(process((politely) T erminate Yes 17 SIGCHLD Child(stopped(or(terminated Ignore Yes 18 SIGCONT Continue(stopped(process Continue((Resume) No 19 SIGSTOP Stop(process((immediately) Stop((Suspend) No 20 SIGTSTP Stop(process((politely) Stop((Suspend) Yes (Ctrl-Z) … Sean Barker 18
Recap: Segmentation Fault int a[1000]; main () { a[5000] = 13; } 80483b7: c7 05 60 e3 04 08 0d movl $0xd,0x804e360 User code Kernel code Excep&on: page fault movl Detect invalid address Signal process Sean Barker 19 Signal Control Flow (1) Signal received (2) Control passes by process to signal handler I curr I next (3) Signal handler runs (4) Signal handler returns to next instruction Sean Barker 20
Signal Handler as Concurrent Flow Process A Process A Process B while (1) handler(){ ; … } Time Sean Barker 21 Signal Handler as Concurrent Flow (alt) Process A Process B Signal delivered user code (main) I curr to process A context switch kernel code user code (main) context switch kernel code Signal received user code (handler) by process A kernel code I next user code (main) Sean Barker 22
Process Groups pid=10 Shell pgid=10 Fore- Back- Back- pid=20 pid=32 pid=40 ground ground ground pgid=20 pgid=32 pgid=40 job #1 job job #2 Background Background process group 32 process group 40 Child Child pid=21 pid=22 pgid=20 pgid=20 Foreground process group 20 Sean Barker 23 Signal Handler as Concurrent Flow Process A Process A Process B while (1) handler(){ ; … } Time Sean Barker 24
! Concurrency Example (1) int main(int argc, char** argv) { ! int pid; ! ! // add handler Signal(SIGCHLD, handler); ! initjobs(); /* Initialize the job list */ ! while (1) { ! if ((pid = fork()) == 0) { /* Child */ ! execve("/bin/date", argv, NULL); ! } ! addjob(pid); /* Add child to job list */ } ! exit(0); ! } ! void handler(int sig) { ! pid_t pid; ! ! while ((pid = waitpid(-1, NULL, 0)) > 0) { /* Reap child */ deletejob(pid); /* Delete the child from the job list */ } ! // handle case where waitpid returns if (errno != ECHILD) ! // -1 but not an error unix_error("waitpid error"); ! } ! Sean Barker 25 Concurrency Example (2) int main(int argc, char** argv) { ! int pid; ! sigset_t mask_all, prev_all; ! sigfillset(&mask_all); ! Signal(SIGCHLD, handler); ! initjobs(); /* Initialize the job list */ ! while (1) { ! if ((pid = fork()) == 0) { /* Child */ ! execve("/bin/date", argv, NULL); ! } ! sigprocmask(SIG_BLOCK, &mask_all, &prev_all); ! addjob(pid); /* Add child to the job list */ ! sigprocmask(SIG_SETMASK, &prev_all, NULL); ! } ! exit(0); ! } ! void handler(int sig) { ! sigset_t mask_all, prev_all; ! pid_t pid; ! sigfillset(&mask_all); ! while ((pid = waitpid(-1, NULL, 0)) > 0) { /* Reap child */ ! sigprocmask(SIG_BLOCK, &mask_all, &prev_all); ! deletejob(pid); /* Delete child from job list */ ! sigprocmask(SIG_SETMASK, &prev_all, NULL); ! } ! if (errno != ECHILD) ! unix_error("waitpid error"); ! } ! Sean Barker 26
! ! Concurrency Example (3) int main(int argc, char** argv) { ! int pid; ! sigset_t mask_all, mask_one, prev_one; ! sigfillset(&mask_all); ! sigemptyset(&mask_one); ! sigaddset(&mask_one, SIGCHLD); ! Signal(SIGCHLD, handler); ! initjobs(); /* Initialize the job list */ ! while (1) { ! sigprocmask(SIG_BLOCK, &mask_one, &prev_one); /* Block SIGCHLD */ ! if ((pid = fork()) == 0) { /* Child process */ ! sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */ ! execve("/bin/date", argv, NULL); ! } ! sigprocmask(SIG_BLOCK, &mask_all, NULL); /* Parent process */ ! addjob(pid); /* Add the child to the job list */ ! sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */ ! } ! exit(0); ! } ! Sean Barker 27 Key System Calls • fork – Create a new process • execve – Run a new program • kill – Send a signal • waitpid – Wait for and/or reap child process • setpgid – Set process group ID • sigprocmask – Block or unblock signals • sigemptyset – Create empty signal set • sigfillset – Add every signal number to set • sigaddset – Add signal number to set • sigdelset – Delete signal number from set • sigsuspend – Wait until signal received Sean Barker 28
Processes Memory Memory Memory Stack Stack Stack Heap Heap Heap … Data Data Data Code Code Code CPU CPU CPU Registers Registers Registers Sean Barker 29 Threads Sean Barker 30
! ! ! Thread Example /* * hello.c - Pthreads "hello, world" program */ ! Thread attributes Thread ID (usually NULL) void* thread(void* vargp); ! int main() { ! Thread routine pthread_t tid; ! pthread_create(&tid, NULL, thread, NULL); ! pthread_join(tid, NULL); ! Thread arguments exit(0); ! (void *p) hello.c } ! Return value (void **p) void* thread(void* vargp) { /* thread routine */ ! printf("Hello, world!\n"); ! return NULL; ! } hello.c Sean Barker 31
Recommend
More recommend