1 / 22

Recitation 8 (Nov. 1)

Outline Process & job control Lab 5 Reminder Lab 5: Due Thursday. Minglong Shao shaoml+213@cs.cmu.edu Office hours: Thursdays 5-6PM Wean Hall 1315. Recitation 8 (Nov. 1). Process & concurrency. int fork(void) Create an identical copy of the parent process

tilly
Télécharger la présentation

Recitation 8 (Nov. 1)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Outline Process & job control Lab 5 Reminder Lab 5: Due Thursday Minglong Shao shaoml+213@cs.cmu.edu Office hours: Thursdays 5-6PM Wean Hall 1315 Recitation 8 (Nov. 1)

  2. 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

  3. Example 1 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 "); } 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 ?

  4. 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 "); } L1 “a “ “e “ “b “ (“d “) “e “ L0 “c “ (“d “) “e “ L2 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 4. b e c e a d e N 3. a b c e e d e Y

  5. 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

  6. Process tree for shell Shell pid=10 pgid=10 Fore- ground job Back- ground job #1 Back- ground job #2 pid=20 pgid=20 pid=32 pgid=32 pid=40 pgid=40 Background process group 32 Backgroud process group 40 Child Child pid=21 pgid=20 pid=22 pgid=20 Each job has a unique process group id int setpgid(pid_t pid, pid_t pgid); setpgid(0, 0); Foreground process group 20

  7. Process tree for tsh UNIX shell pid=5 pgid=5 Foreground job receives SIGINT, SIGTSTP, when you type ctrl-c, ctrl-z pid=10 pgid=10 tsh Forward signals Fore- ground job Back- ground job #1 Back- ground job #2 pid=20 pgid=20 pid=32 pgid=32 pid=40 pgid=40 Background process group 32 Backgroud process group 40 Child Child int kill(pid_t pid, int sig) pid > 0: send sig to specified process pid = 0: send sig to all processes in same group pid < -1: send sig to group -pid pid=21 pgid=20 pid=22 pgid=20 Foreground process group 20

  8. Execute program int execve(const char *fname, char *const argv[], char *const envp[]); Examples: execve(“/bin/ls”, NULL, NULL); execve(“./mytest”, argv, envp); “front-end” functions for execve int 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[]);

  9. Reaping child process waitpid(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 zombied WUNTRACED: report status of terminated or stopped children In Lab 5, use waitpid(-1, &status, WNOHANG|WUNTRACED) In sigchld_handler(): while ((c_pid = waitpid(…)) > 0) { … }

  10. 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

  11. 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?

  12. Busy wait for foreground job In eval(): if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ /* do nothing */ } }

  13. Sleep In eval(): if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ sleep(1); } }

  14. 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.

  15. 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(…); }

  16. An okay schedule Signal Handler Child time Shell fork() addjob() execve() exit() sigchld_handler() deletejobs()

  17. A problematic schedule time Signal Handler Child Shell fork() execve() exit() sigchld_handler() deletejobs() addjob() Job added to job list after the signal handler tried to delete it!

  18. Solution: blocking signals sigchld_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, …) }

  19. I/O redirection • Do it before call execve() in child process eval() { pid = fork(); if(pid == 0) { /* child */ /* Redirect I/O */ if (redirect_input) dup2(…); if (redirect_output) dup2(…); execve(…); } addjob(…); }

  20. 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);

  21. 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!

  22. 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

More Related