15-213, Fall 06
description
Transcript of 15-213, Fall 06
![Page 1: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/1.jpg)
1
15-213, Fall 06
Outline Shell Lab Processes Signals
![Page 2: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/2.jpg)
2
Process IDs & process groups A process has its own, unique process ID
pid_t getpid();
A process belongs to exactly one process group pid_t getpgrp();
A new process belongs to which process group? Its parent’s process group
Make a new process group for myself and my children: setpgid(0, 0);
![Page 3: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/3.jpg)
3
Process & concurrency
int fork(void) Create a new process identical to parent process Return 0 to child process Return child’s pid to the parent process
Any scheduling order of processes is possible!! Unless code uses explicit synchronization Context switching can happen at any point
![Page 4: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/4.jpg)
4
Lab 5
A tiny shell with job control & I/O redirection Key points:
Reap all child processes Handle SIGCHLD, SIGTSTP, SIGINT Avoid race hazards
![Page 5: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/5.jpg)
5
How to Send Signals
To 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 negative
Can we use signals to count events? No Why? Signals not queued!!
![Page 6: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/6.jpg)
6
Signals: sending
OS Kernel
blockedpending1
Process 1 Process 2
other events
OS signal manager
kill(pid, SIGINT)
• divide by zero: SIGFPE
• ctrl-c: SIGINT
• child process exit: SIGCHLD
![Page 7: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/7.jpg)
7
Signals: receiving
OS Kernel
blockedpending
Process 2
OS signal manager
0
OS delivers the pending non-blocked signals
1
![Page 8: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/8.jpg)
8
Key signals in the shell lab
SIGINT Triggered by: Interrupt signal (ctrl-c) Default action: the process terminates
SIGTSTP Triggered by: Stop signal from terminal (ctrl-z) Default action: the process stops Can be restarted later(by sending SIGCONT to it)
SIGCHLD Triggered by: a child process has stopped or
terminated
![Page 9: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/9.jpg)
9
Shell: the process tree
Fore-ground
job
Back-groundjob #1
Back-groundjob #2
Shell
Child Child
pid=10pgid=10
Foregroundprocess group 20
Backgroundprocess group 32
Backgroudprocess group 40
pid=20pgid=20
pid=32pgid=32
pid=40pgid=40
pid=21pgid=20
pid=22pgid=20
Each job has a unique process group idint setpgid(pid_t pid, pid_t pgid);setpgid(0, 0);
![Page 10: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/10.jpg)
10
Process tree for tsh
Fore-ground
job
Back-groundjob #1
Back-groundjob #2
tsh
Child Child
pid=10pgid=10
Foregroundprocess group 20
Backgroundprocess group 32
Backgroudprocess group 40
pid=20pgid=20
pid=32pgid=32
pid=40pgid=40
pid=21pgid=20
pid=22pgid=20
UNIXshell
pid=5pgid=5
Foreground jobreceives SIGINT, SIGTSTP, when you type ctrl-c, ctrl-z
Forward signals
int 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)
![Page 11: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/11.jpg)
11
Execute 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 terminates
The new program overwrites its state and takes its PID
Any signal handlers installed by the caller are reset
![Page 12: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/12.jpg)
12
Reaping terminated child processespid_t waitpid(pid_t pid, int *status, int options)
pid>0: wait for process with PID=pid -1: wait for any process
pid<-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 stopped
WNOHANG|WUNTRACED combination is very useful in the shell lab:it detects all the necessary events, and doesn’t block if no ‘’events’’
![Page 13: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/13.jpg)
13
Reaping terminated child processespid_t waitpid(pid_t pid, int *status, int options)
pid>0: wait for process with PID=pid -1: wait for any process
pid<-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)
![Page 14: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/14.jpg)
14
Status int status;waitpid(pid, &status, WNOHANG|WUNTRACED)
Macros to evaluate status: WIFEXITED(status): process exited normally WEXITSTATUS(status): exit code of the process
WIFSIGNALED(status): process exited because a signal was not caught (SIGINT, SIGKILL, etc.)
WTERMSIG(status): identifies the signal that was not caught
WIFSTOPPED(status): process was stopped WSTOPSIG(status): identifies the stopping signal
![Page 15: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/15.jpg)
15
Reaping child process in tsh
Where to put waitpid(…) ?
As the handout suggests:One centralized reaping for both fg and bg: In sigchld_handler()
![Page 16: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/16.jpg)
16
Busy wait for foreground job
tsh should still wait for fg job to complete, how?
At an appropriate place in eval():
while(fg process still alive){
/* do nothing */
}
![Page 17: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/17.jpg)
17
Better than simple busy-waiting: Sleep
At an appropriate place in eval():
while(fg process still alive){
sleep(1);
}
![Page 18: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/18.jpg)
18
Race hazards
A data structure is shared by two pieces of code that can run concurrently
Different behaviors of program depending upon how the schedule interleaves the execution of code.
![Page 19: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/19.jpg)
19
An example of a race hazard
sigchld_handler() { … waitpid(…)) … { deletejob(pid); }}eval() { pid = fork(); if(pid == 0) { /* child */ execve(…); } /* parent */ /* signal handler may run BEFORE addjob()*/ addjob(…);}
![Page 20: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/20.jpg)
20
Solution: blocking signals
eval() { sigprocmask(SIG_BLOCK, …) pid = fork(); if(pid == 0) { /* child */ sigprocmask(SIG_UNBLOCK, …) execve(…); } /* parent */ /* signal handler might run BEFORE addjob() */ addjob(…); sigprocmask(SIG_UNBLOCK, …)}
![Page 21: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/21.jpg)
21
I/O Redirection
Covered in Chapter 11
Make file descriptor ‘newfd’ a copy of ‘oldfd’:
dup2(int oldfd, int newfd);
Get input from my_infd instead of standard input
dup2(my_infd, STDIN_FILENO);
Make a copy of a file descriptor (standard output in this case):
int my_outfd = dup(STDOUT_FILENO);
![Page 22: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/22.jpg)
22
Reminders
Some important system calls: fork(), execve(), waitpid(), sigprocmask(),
setpgid(), kill() … Check man pages for details about system calls
man 2 kill
Check return values of all system calls Flush output buffers: fflush(stdout);
STEP by STEP Test your shell by typing commands first
Start now!
![Page 23: 15-213, Fall 06](https://reader036.fdocuments.net/reader036/viewer/2022062304/56814609550346895db319e7/html5/thumbnails/23.jpg)
23
What are the possible program outputs?#include <unistd.h>#include <stdio.h>
int cnt = 0;
int main(void){ if (fork() == 0){ cnt ++; // in child fork(); cnt++; } cnt ++; printf("%d", cnt); return 0;}
Possible outputs:133313331