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 Original ¡Unix ¡shell ¡(Stephen ¡Bourne, ¡AT&T ¡Bell ¡Labs, ¡1977) sh [0] “ Bourne-‑Again” ¡Shell, ¡widely ¡used bash default ¡on ¡most ¡Unix/Linux/Mac ¡OS ¡X ¡systems others... init [1] while (true) { Print command prompt. Daemon Read command line from user. Login shell e.g. httpd Parse command line. If command is built-in, do it. Else fork process to execute command. Child Child Child 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): Some ¡programs ¡ run ¡“for ¡a ¡long ¡time” Input ¡(keyboard) Output ¡(screen) $ emacs fizz.txt # shell stuck until emacs exits. A ¡“background” ¡ job ¡is ¡a ¡process ¡we ¡don't ¡want ¡to ¡wait ¡for $ emacs boom.txt & # emacs runs in background [1] 9073 # while shell is... $ gdb ./umbrella # immediately ready for next command don't ¡do ¡this ¡with ¡emacs unless ¡using ¡X ¡windows ¡version 8 9 Signals Managing ¡Background ¡Jobs 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) T erminate Yes 9 SIGKILL Kill ¡process ¡(immediately) T erminate No $ ulimit -u # bash syntax 11 SIGSEGV Segmentation ¡violation T erminate ¡ & ¡Dump Yes 1024 14 SIGALRM Timer ¡signal T erminate Yes Shell ¡must ¡explicitly ¡reap ¡background ¡jobs. 15 SIGTERM Kill ¡process ¡(politely) T erminate 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 Pending ¡and ¡Blocked ¡Signals Another ¡View ¡of ¡Signal ¡ Handlers ¡ as ¡ 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 user ¡ code ¡(main) I curr context ¡ switch 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 Shell: ¡Ctrl-‑C ¡sends ¡SIGINT ¡(Ctrl-‑Z ¡sends ¡SIGTSTP) Every ¡ process ¡belongs ¡to ¡exactly ¡ one ¡process ¡group ¡ to ¡every ¡job ¡in ¡the ¡foreground ¡process ¡group. (default: ¡ parent's ¡ group) SIGINT ¡– default ¡action ¡is ¡to ¡terminate ¡each ¡process ¡ SIGTSTP ¡ – default ¡action ¡is ¡to ¡stop ¡(suspend) ¡each ¡process pid=10 Shell pgid=10 pid=10 Shell pgid=10 Fore-‑ Back-‑ Back-‑ pid=20 pid=32 pid=40 ground ground ground pgid=20 pgid=32 pgid=40 job job ¡#1 job ¡#2 Fore-‑ Back-‑ Back-‑ pid=20 pid=32 pid=40 ground ground ground pgid=20 pgid=32 pgid=40 Background Background job job ¡#1 job ¡#2 process ¡ group ¡ 32 process ¡ group ¡ 40 Child Child Background Background process ¡ group ¡32 process ¡ group ¡40 getpgrp() pid=21 pid=22 Child Child Return ¡process ¡group ¡of ¡current ¡process pgid=20 pgid=20 Foreground ¡ setpgid() pid=21 pid=22 process ¡ group ¡ 20 pgid=20 pgid=20 Change ¡process ¡group ¡of ¡a ¡process Foreground ¡ process ¡ group ¡20 19 20 Signal ¡demos A ¡Program ¡That ¡Reacts ¡to Externally ¡Generated ¡Events ¡(Ctrl-‑c) 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("OK\n"); You think hitting ctrl-c will stop me? exit(0); Well...OK } > main() { signal(SIGINT, handler); /* installs ctrl-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 Can ¡generate ¡from ¡user ¡programs #include <stdio.h> main() { #include <signal.h> signal(SIGALRM, handler); Can ¡define ¡effect ¡by ¡declaring ¡signal ¡handler alarm(1); /* send SIGALRM in Some ¡caveats int beeps = 0; 1 second */ Very ¡high ¡overhead /* SIGALRM handler */ while (1) { >10,000 ¡clock ¡cycles void handler(int sig) { safe_printf("BEEP\n"); } Only ¡use ¡for ¡exceptional ¡conditions } Not ¡queued if (++beeps < 5) alarm(1); Just ¡one ¡bit ¡for ¡each ¡pending ¡signal ¡type > ./internal else { BEEP Many ¡more ¡complicated ¡details ¡we ¡have ¡not ¡discussed. safe_printf("DING DING!\n"); BEEP exit(0); Book ¡goes ¡into ¡too ¡much ¡gory ¡detail. BEEP } BEEP } BEEP internal.c DING DING! > 33 42 5
Recommend
More recommend