Program That Runs Other Programs Unix/Linux Process Hierarchy Shell
Total Page:16
File Type:pdf, Size:1020Kb
shell: program that runs other programs Building a Shell 1 5 Unix/Linux Process Hierarchy shell program that runs other programs on behalf of the user sh Original Unix shell (Stephen Bourne, AT&T Bell Labs, 1977) [0] bash “Bourne-Again” Shell, widely used default on most Unix/Linux/Mac OS X systems others.. init [1] while (true) { Print command prompt. Daemon Login shell Read command line from user. e.g. httpd Parse command line. If command is built-in, do it. Child Child Child Else fork process to execute command. in child: Execute requested command with execv. (never returns) Grandchild Grandchild in parent: Wait for child to complete. } 6 7 1 terminal ≠ shell Background vs. Foreground User interface to shell and other programs. Users generally run one command at a time Graphical (GUI) vs. command-line (CLI) Type command, read output, type another command Command-line terminal (emulator): Input (keyboard) Some programs run “for a long time” Output (screen) $ emacs fizz. txt # shell stuck until ema cs exi ts. A “background” job is a process we don't want to wait for $ emacs boom. txt & # em acs ru ns in backg round [1] 9073 # wh ile sh ell i s... $ gdb ./ umbre lla # im mediat ely r eady f or nex t com mand don't do this with emacs un l es s u si n g X wi nd o ws vers i o n 8 9 Managing Background Jobs Signals Signal: small message notifying a process of event in system Shell waits for and reaps foreground jobs. like exceptions and interrupts sent by kernel, sometimes at request of another process Background jobs become zombies when they terminate. ID is entire message Shell might run for a really long time! ID Name Corresponding Event Default Action Can Kernel may run out of memory! Override? fork() returns -1 if per-user process quota exceeded 2 SIGINT Interrupt (Ctrl-C) Te r m i n a t e Yes $ ul imi t -u # b ash sy nta x 9 SIGKILL Kill process (immediately) Te r m i n a t e No 1024 11 SIGSEGV Segmentation violation Te r m i n a t e & D u m p Yes 14 SIGALRM Timer signal Te r m i n a t e Yes Shell must explicitly reap background jobs. 15 SIGTERM Kill process (politely) Te r m i n a t e Yes One way: check/reap any completed background jobs before every prompt. 17 SIGCHLD Child stopped or terminated Ignore Yes OK, assuming foreground jobs/user inactivity are not too long. 18 SIGCONT Continue stopped process Continue (Resume) No Another way: OS delivers signal via exceptional control flow when child ends. 19 SIGSTOP Stop process (immediately) Stop (Suspend) No OK to respond by reaping, but complicated concurrency makes it tricky. 20 SIGTSTP Stop process (politely) Stop (Suspend) Yes 10 … 12 2 Sending/Receiving a Signal Signals Handlers as Concurrent Flows Kernel sends (delivers) a signal to a destination process by updating state in the context of the destination process. Signal handlers run concurrently with main program (in same process). Reasons: System event, e.g. segmentation fault (SIGSEGV) Another process used kill system call: explicitly request the kernel send a signal to the destination process Process A Process A Process B while (1) handler(){ Destination process receives signal when kernel forces it to react. ; … } Reactions: Ignore the signal (do nothing) Time Terminate the process (with optional core dump) Catch the signal by executing a user-level function called signal handler Like an impoverished Java exception handler 13 15 Another View of Signal Handlers as Pending and Blocked Signals Concurrent Flows A signal is pending if sent but not yet received <= 1 pending signal per type per process Process A Process B No Queue! Just a bit per signal type. Signals of type S discarded while process has S signal pending. Signal delivered Icurr user code (main) kernel code context switch A process can block the receipt of certain signals user code (main) Receipt delayed until the signal is unblocked kernel code context switch Signal received user code (handler) A pending signal is received at most once kernel code I next user code (main) Let's draw a picture... 16 17 3 Sending Signals from the Keyboard Process Groups Every process belongs to exactly one process group Shell: Ctrl-C sends SIGINT (Ctrl-Z sends SIGTSTP) to every job in the foreground process group. (default: parent's group) SIGINT – default action is to terminate each process pid=10 SIGTSTP – default action is to stop (suspend) each process pgid=10 Shell pid=10 pgid=10 Shell Fore- Bac k- Bac k- pid=20 pid=32 ground ground ground pid=40 pgid=20 pgid=32 pgid=40 job job #1 job #2 Fore- Bac k- Bac k- pid=20 pid=32 pid=40 pgid=20 ground ground ground Background pgid=32 pgid=40 Background job job #1 job #2 process group 32 process group 40 Child Child Background Background getp grp () process group 32 process group 40 pid=21 pid=22 Child Child pgid=20 pgid=20 Return process group of current process Foreground setp gid () pid=21 pid=22 process group 20 Change process group of a process pgid=20 pgid=20 Foreground process group 20 19 20 Signal demos A Program That Reacts to Ctrl-C Externally Generated Events (Ctrl-c) #include <stdlib.h> Ctrl-Z #include <stdio.h> #include <signal.h> void handler(int sig) { kill safe_printf("You think hitting ctrl-c will stop me?\n"); sleep(2); safe_printf("Well..."); > ./external kill(pid, SIGINT); sleep(1); <ctrl-c> printf(" O K \n"); You think hitting ctrl-c will stop me? exit(0); Well...OK } > main() { signal(SIGINT, handler); /* installs ct r l -c handler */ while(1) { } } external.c 21 32 4 A Program That Reacts to Internally Signal summary Generated Events Signals provide process-level exception handling #include <stdio.h> main() { Can generate from user programs #include <signal.h> signal(SIGALRM, handler); Can define effect by declaring signal handler alarm(1); /* send SIGALRM in int beeps = 0; 1 second */ Some caveats Very high overhead /* SIGALRM handler */ while (1) { void handler(int sig) { >10,000 clock cycles safe_printf("BEEP\n"); } } Only use for exceptional conditions if (++beeps < 5) Not queued alarm(1); > ./internal else { Just one bit for each pending signal type BEEP safe_printf("DING DING!\n"); BEEP Many more complicated details we have not discussed. exit(0); BEEP } Book goes into too much gory detail. BEEP } BEEP internal.c DING DING! > 33 42 5.