CS241 Systems ProgrammingOutlineProcessesProcess Creation with fork()Differences between parent and childfork() Example 1fork() example 2Example 2 cont’dSlide 9Orphans and ZombiesPowerPoint PresentationSolution: wait(…)wait cont’dwait(...) macrosExample 3: waitProblem 4execSlide 18exec variationsexec variations: passing parametersexec variations: command pathexec variations (cont’d)fork + execExample 5: execProblem 6: p6-exec.cCS241 Systems ProgrammingDiscussion Section Week 21/29/07 – 2/02/07Stephen KloderOutlineProcessesforkwaitexecProcessesA process is an instance of a running programA process contains:Instructions (i.e. the program)Resources (variables, buffers, links, etc.)State (identity, ready/running/locked, etc.)Processes can create other processesfork() creates a new process:Process Creation with fork()envstackfreeheapstaticcodeThe new (child) process is identical to the old (parent) process, except…envstackfreeheapstaticcodefork()createsParent ChildDifferences between parent and childProcess ID (getpid())Parent ID (getppid())Return value of fork()In parent, fork() returns child pidIn child, fork() returns 0fork() Example 1What does this do?fprintf(stdout,”%d\n”,fork());Try it!fork() example 2 #include <stdio.h>#include <sys/types.h>#include <unistd.h>int main(int argc, char** argv) {pid_t child_pid = fork();if (child_pid < 0) { // error codeperror(“Fork Failed”);return –1;} fprintf(stdout, “I am process %d\n”,getpid());if (child_pid == 0) { // child codefprintf(stdout,”I’m the child process.\n”);} else { // parent codefprintf(stdout,”I’m the parent of child process %d.\n”, child_pid);}return 0;}Example 2 cont’dThis exits too quickly; let’s slow it down:if (child_pid == 0) { // child codesleep(15);fprintf(stdout,”I’m the child process.\n”);} else { // parent codesleep(20);fprintf(stdout,”I’m the parent of child process %d.\n”, child_pid);}Example 2 cont’dIn a second window, run ps –a, and look for the pids from the program output.Periodically run ps –a again, as the program in the first window executes.What happens when the program runs?What happens when the child finishes?What happens when the parent finishes?What happens when you switch the parent and child sleep statements?Orphans and ZombiesWhen a process finishes, it becomes a zombie until its parent cleans up after it.If its parent finishes first, the process becomes an orphan, and the init process (id 1) adopts it.How can a parent know when its children are done?Solution: wait(…) wait() allows a parent to wait for its child process, and save its return valuepid= wait(&status , options);pid= waitpid(pid , &status ,options);wait() waits for any child; waitpid() waits for a specific child.wait cont’dwait() blocks until child finisheswait() does not block if the option WNOHANG is included. When would we want to use this?The child’s return value is stored in *statuswait(...) macrosWIFEXITED(status) is true iff the process terminated normally.WEXITSTATUS(status) gives the last 8 bits of the process’s return value (assuming normal exit)Example 3: wait#include <sys/wait.h>……// add this to parent codeif (waitpid(child_pid, &result, 0) == -1) {perror(”Wait failed”);return -1;}if( WIFEXITED(result)) {fprintf(stdout, ”child %d returned %d\n”, child_pid, WEXITSTATUS(result));Problem 4Recall Example 2. How can we use wait to clean up the zombie process?execexecexec replaces the current process image(code, variables, etc.) with that of a new program:envstackfreeheapstaticcodeenv*NewProgramexec* The program may choose to change the environmentBefore Afterexec variationsThere are 6 different ways of calling exec. Which one to use depends on three conditions:1. How arguments are passed2. How the path is specified3. Whether a new environment is usedexec variations: passing parametersexec can have parameters passed to it two different ways:List of parameters:execl(“/usr/bin/ls”, ”ls”, ”-l”, NULL);Argument Vector (like argv):execv(argv[1],argv+1);Q: When would you use execl? When would you use execv?exec variations: command pathAdding a “p” to an exec call tells the system to look for the command in the environment’s path.Compare:execl(“/usr/bin/ls”, ”ls”, ”-l”, NULL);execlp(“ls”, ”ls”, ”-l”, NULL);The difference is similar for execv and execvp.exec variations (cont’d)By default, the new program inherits the old program’s environment. Adding an “e” to the exec call allows the new program to run with a new environment **environexecve and execle allow the user to specify the environment. The others inherit the old environment.fork + execIf exec succeeds, it does not return, as it overwrites the program.No checking return values, executing multiple commands, monitoring results, etc.Solution: fork a new process, and have the child run execExample 5: exec #include <unistd.h>#include <stdio.h>int main(int argc, char** argv) {child_pid = fork();if (child_pid < 0) {perror(“Fork failed”);return –1;} else if (child_pid == 0) {if (execvp(argv[1], argv+1) < 0) {fprintf(stderr,”Failed to execute %s!\n”, argv[1]);perror(”child exec:”);return -1;}} // What belongs here?...return 0;}Problem 6: p6-exec.cCompile and run this program. It seems to use fork and exec to run a list of argument-free commands (ls, cal, etc.) from a file commands.What’s wrong with this program? What happens when you run it?How can you fix
View Full Document