Recitation 8 (Nov. 1) Outline Process & job control Lab 5 Reminder Lab 5: Due Thursday Minglong Shao...
-
Upload
alonso-solomon -
Category
Documents
-
view
214 -
download
0
Transcript of Recitation 8 (Nov. 1) Outline Process & job control Lab 5 Reminder Lab 5: Due Thursday Minglong Shao...
Recitation 8 (Nov. 1)
Outline Process & job control Lab 5
Reminder Lab 5:
Due Thursday
Minglong [email protected]
Office hours:Thursdays 5-6PMWean Hall 1315
Process & concurrency
int fork(void) Create an identical copy of the parent process Return values differentiate parent from child
Any scheduling order of processes are possible Unless code explicitly imposes some order
(synchronization) Context switching can happen at any point
Example 1int main(){ pid_t pid;
if((pid = fork()) == 0) { printf("a "); } else { printf("b "); if(fork() == 0) { printf("c "); } } if(waitpid(pid, NULL, 0) > 0) printf("d ");
printf("e ");}
Possible outputs
1. a b c d e e e ?2. b a e c d e e ?3. a b c e e d e ?4. b e c e a d e ?
Example 1 (cont.)int main(){ pid_t pid;
if((pid = fork()) == 0) { printf("a "); } else { printf("b "); if(fork() == 0) { printf("c "); } } if(waitpid(pid, NULL, 0) > 0) printf("d ");
printf("e ");}
L0
L1
“b “
L2
“a “ “e “
(“d “)
(“d “)“c “
“e “
“e “
In L1, pid = 0 wait for any child process
In L0 and L2, pid is the process id of L1 wait for process L1
1. a b c d e e e N 2. b a e c d e e Y
3. a b c e e d e Y 4. b e c e a d e N
Lab 5
A tiny shell (tsh) with job control & I/O redirection Key points:
Reap all child processes Handle SIGCHLD, SIGTSTP, SIGINT Avoid race hazard
Process tree for shell
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);
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 specified processpid = 0: send sig to all processes in same grouppid < -1: send sig to group -pid
Execute programint execve(const char *fname, char *const argv[], char *const envp[]);Examples:execve(“/bin/ls”, NULL, NULL);execve(“./mytest”, argv, envp);
“front-end” functions for execveint execl(const char* path, const char *arg, …);int execlp(const char* file, const char *arg, …);int execle(const char*path, const char *arg, … char
* const envp[]);int execv(const char *path, char *const argv[]);int execvp(const char *file, char *const argv[]);
Reaping child processwaitpid(pid_t pid, int *status, int options)
pid: wait for child process with pid (process id or group id)-1: wait for any child process
status: tell why child terminated
options:WNOHANG: return immediately if no children zombiedWUNTRACED: report status of terminated or stopped children
In Lab 5, usewaitpid(-1, &status, WNOHANG|WUNTRACED)
In sigchld_handler():while ((c_pid = waitpid(…)) > 0) { … }
Check status int status;waitpid(pid, &status, WNOHANG|WUNTRACED)
Macros to evaluate status: WIFEXITED(status): child exited normally WEXITSTATUS(status): returns code when child exits
WIFSIGNALED(status): child exited because a signal is not caught
WTERMSIG(status): gives the terminating signal number
WIFSTOPPED(status): child is currently stopped WSTOPSIG(status): gives the stop signal number
Reaping child process in tsh
Where to put waitpid(…)
Two waits In sigchld_handler(): for bg processes In eval(): for fg processes
One wait In sigchld_handler(): for both tsh should still wait for fg job to complete, how?
Busy wait for foreground job
In eval():
if(fork() != 0) { /* parent */
addjob(…);
while(fg process still alive){
/* do nothing */
}
}
Sleep
In eval():
if(fork() != 0) { /* parent */
addjob(…);
while(fg process still alive){
sleep(1);
}
}
Race hazard
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.
An example of race hazard
sigchld_handler() { while ((pid = waitpid(…)) > 0){ deletejob(pid); }}eval() { pid = fork(); if(pid == 0) { /* child */ execve(…); } /* parent */ /* signal handler may run BEFORE addjob()*/ addjob(…);}
An okay schedule
Shell Signal Handler Child
fork()
addjob()
execve()
exit()
sigchld_handler()
deletejobs()
time
A problematic schedule
Shell Signal Handler Child
fork()
execve()
exit()
sigchld_handler()
deletejobs()
time
addjob()
Job added to job list after the signal handler tried to delete it!
Solution: blocking signalssigchld_handler() { pid = waitpid(…); deletejob(pid);}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, …)}
I/O redirection Do it before call execve() in child processeval() { pid = fork(); if(pid == 0) { /* child */ /* Redirect I/O */ if (redirect_input) dup2(…);
if (redirect_output) dup2(…); execve(…); } addjob(…);}
dup2(int oldfd, int newfd) Covered in Chapter 11
oldfd: old file descriptor
newfd: new file descriptor
Some examples:
Get input from my_infd instead of standard input
dup2(my_infd, STDIN_FILENO);
Print output to my_outfd instead of standard output
dup2(my_outfd, STDOUT_FILENO);
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
STEP by STEP Test your shell by typing commands first I/O redirection: last step (15 pts out of 135 pts)
Start now!
Virtual memory
One of the most important concepts in CS Why use virtual memory (VM)
Use RAM as a cache for disk Easier memory management Access protection Enable “partial swapping” Share memory efficiently