<<

shell: program that runs other programs

Building a Shell

1 5

Unix/ Hierarchy shell program that runs other programs on behalf of the user sh Original shell (Stephen Bourne, &T Bell Labs, 1977) [0] “Bourne-Again” Shell, widely used default on Unix/Linux/Mac OS X systems others.. . init [1] while (true) { Print 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: for child to complete. } 6 7

1 ≠ shell Background vs. Foreground to shell and other programs. Users generally run one command at a Graphical (GUI) vs. command-line (CLI) 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 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 (Ctrl-C) Te r m i n a t e $ ul imi t -u # b ash sy nta x 9 SIGKILL 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. (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 ) 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 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 Ctrl-Z #include #include

void handler(int sig) { kill safe_printf("You think hitting ctrl-c will stop me?\n"); (2); safe_printf("Well..."); > ./external kill(pid, SIGINT); sleep(1); (" O K \n"); You think hitting ctrl-c will stop me? (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 main() { Can generate from user programs #include 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 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