Shell Execution Call fork Basic fork child execs
Shell Execution Call fork Basic: • fork, child execs, parent waits • code of program in box RC=0 No Yes – RC == return value from fork() Call exec Subsequent instructions Wait on child
Useful Facts • A process exec’d retains its caller’s file table – redirection is maintained – pipes are maintained • Note that the data space is not maintained, so variables in caller are not available to callee – How does this affect < , > , and | ? ?
Shell Execution: Additional Considerations • Piping (using pipe symbol | in command) – e. g. >ls –l | more • displays long directory listing with pagination • Input/Output Redirection (< or > symbols) – e. g. >ls > dir. txt • outputs directory listing to file dir. txt (no display) – e. g. more < ls –l • same result as first example above
Complex Shell Execution >ls –l | more • Requires concurrent execution of two programs, ls and more – must fork twice to get one process for each – must set up pipe to allow ls to send data to more. When to set it up? – ls produces data that is piped to more • ls’ std. output is redirected to write end of pipe • more’s std input is redirected to read end of pipe
Parent Child ls Child more pipe Call fork Yes RC=0 Redirect cout to write end of pipe Close unused pipe end(s) (how many? ) No Call fork Call exec ls Call exec more Yes RC=0 No Wait on children Error Handling
Complex Shell Execution >ls > dir. txt • Requires only one process • Redirect cout to file “dir. txt” • Exec ls
Buffering of I/O • Line Buffering – stream buffer is flushed when newline enters stream • cout • Full Buffering – stream buffer is flushed only when full; minimizes disk access • files • No Buffering – Direct • cerr • redirected cout becomes fully buffered - almost
Buffering of I/O: Example // File: Buffer. cpp // Demonstrate full vs. line buffering. // Write a string to cout. // If run with output redirected, should appear twice! // Try changing cout to cerr – Surprise! Need to use >& // to redirect. But, it still isn’t buffered #include <sys/types. h> #include <unistd. h> #include <iostream> using namespace std; int main() {cout << "ABCDn"; fork(); cout. flush(); }
Buffering of I/O: Another Example // File: Buffer 2. cpp // Demonstrate full vs. line buffering. Check when things come out! // Note that parent is forced to follow child // Try changing cout to cerr #include <sys/types. h> #include <unistd. h> #include <iostream> using namespace std; int main() {pid_t pid; cout << "ABCDn"; // if sub endl for n, still line buffered!!! if (pid=fork()) { wait(NULL); cout << "Parent!n"; } else cout << "Child!n"; cout. flush(); }
Exercises • Show possible execution of > ls –l | more with only one fork in the parent • Describe steps necessary to execute command >ls | grep “g” | more
- Slides: 10