Shell Execution Basic: fork, child execs, parent waits code of program in box –RC == return value from fork() Call fork RC=0 Call exec Subsequent instructions Wait on child No Yes
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 ( 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
Call fork RC=0 Call fork Wait on children No Child ls Redirect cout to write end of pipe Call exec ls Error Handling Parent pipe Yes RC=0 No Yes Close unused pipe end(s) (how many?) Child more Redirect cout to write end of pipe Call exec more Error Handling Close unused pipe end(s) (how many?)
>ls > dir.txt Requires only one process Redirect cout to file “dir.txt” Exec ls Complex Shell Execution
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 using namespace std; int main() {cout << "ABCD\n"; fork(); cout.flush(); }
Buffering of I/O: Another Example // File: Buffer2.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 using namespace std; int main() {pid_t pid; cout << "ABCD\n"; // 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