1 1 Process Management!2 Goals of this Lecture!• Help you learn about:"• Creating new processes"• Programmatically redirecting stdin, stdout, and stderr"• (Appendix) communication between processes via pipes"• Why?"• Creating new processes and programmatic redirection are fundamental tasks of a Unix shell (Assignment 7)"• A power programmer knows about Unix shells, and thus about creating new processes and programmatic redirection"2 3 Why Create a New Process?!• Run a new program"• E.g., shell executing a program entered at command line"• Or, even running an entire pipeline of commands"• Such as “wc –l * | sort | uniq -c | sort –nr”"• Run a new thread of control for the same program"• E.g., a Web server handling a new Web request"• While continuing to allow more requests to arrive"• Essentially time sharing the computer"• Underlying mechanism"• A process executes fork() to create a child process"• (Optionally) child process does exec() of a new program"4 Creating a New Process!• Cloning an existing process"• Parent process creates a new child process"• The two processes then run concurrently "• Child process inherits state from parent "• Identical (but separate) copy of virtual address space"• Copy of the parentʼs open file descriptors"• Parent and child share access to open files"• Child then runs independently"• Executing independently, including invoking a new program"• Reading and writing its own address space"parent child3 5 Fork System-Level Function!• fork() is called once"• But returns twice, once in each process"• Telling which process is which "• Parent: fork() returns the childʼs process ID"• Child: fork() returns 0"pid = fork(); if (pid != 0) { /* in parent */ … } else { /* in child */ … } 6 Fork and Process State!• Inherited"• User and group IDs"• Signal handling settings"• Stdio"• File pointers"• Root directory"• File mode creation mask"• Resource limits"• Controlling terminal"• All machine register states"• Control register(s)"• …"• Separate in child"• Process ID"• Address space (memory)"• File descriptors"• Parent process ID"• Pending signals"• Time signal reset times"• …"4 7 Example: What Output?!int main(void) { pid_t pid; int x = 1; pid = fork(); if (pid != 0) { printf("parent: x = %d\n", --x); exit(0); } else { printf("child: x = %d\n", ++x); exit(0); } } 8 Executing a New Program!• fork() copies the state of the parent process"• Child continues running the parent program"• … with a copy of the process memory and registers"• Need a way to invoke a new program"• In the context of the newly-created child process"• Example"execvp("ls", argv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); program"NULL-terminated array"Contains command-line arguments$(to become “argv[]” of ls)"5 9 Waiting for the Child to Finish!• Parent may want to wait for children to finish"• Example: a shell waiting for operations to complete"• Waiting for a child to terminate: wait() • Blocks until some child terminates"• Returns the process ID of the child process"• Or returns -1 if no children exist (i.e., already exited)"• Waiting for specific child to terminate: waitpid() • Blocks till a child with particular process ID terminates"#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options); 10 Example: A Simple Shell!• Shell is the parent process"• E.g., bash"• Parses command line"• E.g., “ls –l”"• Invokes child process"• fork(), execvp() • Waits for child"• wait() fork" ls"wait"execvp"bash"child" parent"6 11 Simple Shell Code!Parse command line Assign values to somepgm, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid = wait(&status); Repeat the previous 12 Parse command line Assign values to somepgm, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid = wait(&status); Repeat the previous Simple Shell Trace (1)!Parent Process"Parent reads and parses command line"Parent assigns values to somepgm and someargv7 13 Parse command line Assign values to somepgm, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid = wait(&status); Repeat the previous Simple Shell Trace (2)!Parse command line Assign values to somefile, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid = wait(&status); Repeat the previous Parent Process" Child Process"executing"concurrently"fork() creates child process"Which process gets the CPU first? Letʼs assume the parent…"14 Simple Shell Trace (3)!In parent, pid != 0; parent waits; OS gives CPU to child"Parse command line Assign values to somepgm, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid = wait(&status); Repeat the previous Parse command line Assign values to somefile, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid = wait(&status); Repeat the previous Parent Process" Child Process"childʼs pid"executing"concurrently"8 15 Simple Shell Trace (4)!In child, pid == 0; child calls execvp() Parse command line Assign values to somepgm, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid = wait(&status); Repeat the previous Parse command line Assign values to somefile, someargv pid = fork(); if (pid == 0) { /* in child */ execvp(somepgm, someargv); fprintf(stderr, "exec failed\n"); exit(EXIT_FAILURE); } /* in parent */ pid =
View Full Document