15-213, Fall 06Process IDs & process groupsProcess & concurrencyLab 5How to Send SignalsSignals: sendingSignals: receivingKey signals in the shell labShell: the process treeProcess tree for tshExecute programReaping terminated child processesSlide 13StatusReaping child process in tshBusy wait for foreground jobBetter than simple busy-waiting: SleepRace hazardsAn example of a race hazardSolution: blocking signalsI/O RedirectionRemindersWhat are the possible program outputs?115-213, Fall 06OutlineShell LabProcessesSignals2Process IDs & process groupsA process has its own, unique process IDpid_t getpid();A process belongs to exactly one process grouppid_t getpgrp();A new process belongs to which process group?Its parent’s process groupMake a new process group for myself and my children:setpgid(0, 0);3Process & concurrencyint fork(void)Create a new process identical to parent processReturn 0 to child processReturn child’s pid to the parent processAny scheduling order of processes is possible!!Unless code uses explicit synchronizationContext switching can happen at any point4Lab 5A tiny shell with job control & I/O redirectionKey points:Reap all child processesHandle SIGCHLD, SIGTSTP, SIGINTAvoid race hazards5How to Send SignalsTo a single process:int kill(pid_t pid, int sig)To every process in group abs(gid):int kill(pid_t gid, int sig), where gid is negativeCan we use signals to count events?NoWhy? Signals not queued!!6Signals: sendingOS Kernelblockedpending1Process 1Process 2other eventsOS signal managerkill(pid, SIGINT)• divide by zero: SIGFPE• ctrl-c: SIGINT• child process exit: SIGCHLD7Signals: receivingOS KernelblockedpendingProcess 2OS signal manager0OS delivers the pending non-blocked signals18Key signals in the shell labSIGINTTriggered by: Interrupt signal (ctrl-c)Default action: the process terminatesSIGTSTPTriggered by: Stop signal from terminal (ctrl-z)Default action: the process stopsCan be restarted later(by sending SIGCONT to it)SIGCHLDTriggered by: a child process has stopped or terminated9Shell: the process treeFore-groundjobBack-groundjob #1Back-groundjob #2ShellChild Childpid=10pgid=10Foregroundprocess group 20Backgroundprocess group 32Backgroudprocess group 40pid=20pgid=20pid=32pgid=32pid=40pgid=40pid=21pgid=20pid=22pgid=20Each job has a unique process group idint setpgid(pid_t pid, pid_t pgid);setpgid(0, 0);10Process tree for tshFore-groundjobBack-groundjob #1Back-groundjob #2tshChild Childpid=10pgid=10Foregroundprocess group 20Backgroundprocess group 32Backgroudprocess group 40pid=20pgid=20pid=32pgid=32pid=40pgid=40pid=21pgid=20pid=22pgid=20UNIXshellpid=5pgid=5Foreground jobreceives SIGINT, SIGTSTP, when you type ctrl-c, ctrl-zForward signalsint kill(pid_t pid, int sig)pid > 0: send sig to process with PID=pidpid = 0: send sig to all processes in my grouppid = -1: send sig to all processes with PID>1pid < -1: send sig to group abs(pid)11Execute programint execve(const char *fname, char *const argv[], char *const envp[]);Examples:execve(“/bin/ls”, NULL, NULL);execve(“./mytest”, argv, envp);What happens to the caller process?It effectively terminatesThe new program overwrites its state and takes its PIDAny signal handlers installed by the caller are reset12Reaping terminated child processespid_t waitpid(pid_t pid, int *status, int options) pid>0: wait for process with PID=pid -1: wait for any processpid<-1: wait for any process from group abs(pid)By default, waitpid blocks until at least one zombie process becomes available.options:WNOHANG: return immediately if no zombies availableWUNTRACED: also return if some process has been stoppedWNOHANG|WUNTRACED combination is very useful in the shell lab:it detects all the necessary events, and doesn’t block if no ‘’events’’13Reaping terminated child processespid_t waitpid(pid_t pid, int *status, int options) pid>0: wait for process with PID=pid -1: wait for any processpid<-1: wait for any process from group abs(pid)Return value:pid of the process that exited,or zero if WNOHANG was used and no zombie process available,or -1 on error (then see errno)status: gives info on why the process terminated (or stopped if WUNTRACED used)14Statusint status;waitpid(pid, &status, WNOHANG|WUNTRACED)Macros to evaluate status:WIFEXITED(status): process exited normallyWEXITSTATUS(status): exit code of the processWIFSIGNALED(status): process exited because a signal was not caught (SIGINT, SIGKILL, etc.)WTERMSIG(status): identifies the signal that was not caughtWIFSTOPPED(status): process was stoppedWSTOPSIG(status): identifies the stopping signal15Reaping child process in tshWhere to put waitpid(…) ?As the handout suggests:One centralized reaping for both fg and bg:In sigchld_handler()16Busy wait for foreground jobtsh should still wait for fg job to complete, how?At an appropriate place in eval():while(fg process still alive){ /* do nothing */ }17Better than simple busy-waiting: SleepAt an appropriate place in eval():while(fg process still alive){ sleep(1); }18Race hazardsA data structure is shared by two pieces of code that can run concurrentlyDifferent behaviors of program depending upon how the schedule interleaves the execution of code.19An example of a race hazardsigchld_handler() { … waitpid(…)) … { deletejob(pid); }}eval() { pid = fork(); if(pid == 0) { /* child */ execve(…); } /* parent */ /* signal handler may run BEFORE addjob()*/ addjob(…);}20Solution: blocking signalseval() { sigprocmask(SIG_BLOCK, …) pid = fork(); if(pid == 0) { /* child */ sigprocmask(SIG_UNBLOCK, …) execve(…); } /* parent */ /* signal handler might run BEFORE addjob() */ addjob(…); sigprocmask(SIG_UNBLOCK, …)}21I/O RedirectionCovered in Chapter 11Make file descriptor ‘newfd’ a copy of ‘oldfd’:dup2(int oldfd, int newfd);Get input from my_infd instead of standard inputdup2(my_infd, STDIN_FILENO);Make a copy of a file descriptor (standard output in this case):int my_outfd = dup(STDOUT_FILENO);22RemindersSome important system calls:fork(), execve(), waitpid(), sigprocmask(), setpgid(), kill() …Check man pages for details about system callsman 2 killCheck return values of all system callsFlush output buffers: fflush(stdout);STEP by STEPTest your
View Full Document