Lien000034
2014-10-05
1 Process Control trilogy Overview
UNIX provides basic process control primitives such as fork, exec, exit, and wait. With these process control primitives, we can complete basic operations such as process creation, execution, and termination. Process control can be divided into trilogy,
• Part 1: fork creates a new process.
• Part 2: Execute the new program with exec.
• Part III: exit and wait processing termination and waiting for termination.
2 Part 1: fork create a new process
In an existing process, we can call the fork function to create a new process,
# Include <unistd. h>
Pid_t fork (void );
Returned value: 0 is returned for the child process, and the ID of the child process is returned for the parent process. If an error occurs,-1 is returned.
A new process created by fork is called a sub-process. The fork function is called once, but returns two. The only difference between the two responses is that the return value of the child process is 0, and that of the parent process is the ID of the new Child process. Because the UNIX system does not provide a function to obtain the IDs of all child processes of a process, the parent process can obtain the ID of the child process through the return value of the fork function and perform subsequent processing. In a child process, you can call the getppid function to obtain the ID of the parent process.
After the fork function is returned, both the child process and the parent process continue to execute the commands after the fork call. A child process is a copy of the parent process. For example, a child process obtains a copy of the data space, heap, and stack of the parent process. However, the Parent and Child processes share the body segment.
Example:
The following program calls fork to create a new process and prints the current process ID and parent process ID in both parent and child processes.
#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <errno.h>intmain(void){ pid_t pid; printf("before fork\n"); if ((pid = fork()) < 0) { printf("fork error: %s\n", strerror(errno)); exit(-1); } else if (pid == 0) { printf("in child process, process ID: %d, parent process ID: %d\n", getpid(), getppid()); } else { printf("in parent process, process ID: %d, child process ID: %d\n", getpid(), pid); sleep(1); } exit(0);}
Compile the program, generate the forkdemo file, and then execute the file,
lienhua34:demo$ gcc -o forkdemo forkdemo.clienhua34:demo$ ./forkdemobefore forkin parent process, process ID: 3499, child process ID: 3500in child process, process ID: 3500, parent process ID: 3499
Part 2: exec execute new program
After a child process is created using the fork function, the child process usually calls one exec function to execute another program. When a process calls an exec function, the Program executed by the process is completely replaced with a new program, and the new program is executed from its main function. The process ID is not changed because no new process is created when exec is called. Exec replaces the body, Data, heap, and stack segments of the current process with a new program.
UNIX provides six different exec functions. Here we only describe one of them,
# Include <unistd. h>
Int execv (const char * pathname, char * const argv []);
Returned value: if an error occurs,-1 is returned. If the error succeeds, no value is returned.
The pathname is the path of the new program file to be executed by the process, and the argv parameter is the parameter list to be passed to the new program.
Example:
We have a program file named sayhello. C. The Code is as follows,
#include <stdio.h>#include <stdlib.h>intmain(void){ printf("Hello World! process ID: %d\n", getpid()); exit(0);}
Compile the sayhello. C program and generate the execution file sayhello,
lienhua34:demo$ gcc -o sayhello sayhello.clienhua34:demo$ pwd/home/lienhua34/program/c/apue/ch08/demolienhua34:demo$ ./sayhelloHello World! process ID: 3545
In the execdemo. C program file, we create a new process through fork, and then call the execv function in the sub-process to execute the sayhello file. The Code is as follows,
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>char sayhelloPath[] = "/home/lienhua34/program/c/apue/ch08/demo/sayhello";intmain(void){ pid_t pid; if ((pid = fork()) < 0) { printf("fork error: %s\n", strerror(errno)); exit(-1); } else if (pid == 0) { printf("in child process, process ID: %d, parent process ID: %d\n", getpid(), getppid()); if (execv(sayhelloPath, NULL) < 0) { printf("execv error: %s\n", strerror(errno)); exit(-1); } } else { printf("in parent process, process ID: %d, child process ID: %d\n", getpid(), pid); sleep(2); } exit(0);}
Compile the execdemo. c file, generate and execute the execdemo file,
lienhua34:demo$ gcc -o execdemo execdemo.clienhua34:demo$ ./execdemoin parent process, process ID: 3561, child process ID: 3562in child process, process ID: 3562, parent process ID: 3561Hello World! process ID: 3562
The preceding running result shows that the sub-process (ID: 3562) runs the sayhello file normally.
4 Part 3: exit and wait processing termination and waiting for termination
The exit function provides the Process Termination function. In the article "Process Termination", we have learned the basic knowledge of the exit function. Here we will add the Process Termination status. When learning the exit function, we know that the exit function parameter is used as the exit status of the program ). When a process is terminated, the kernel regards the exit state of the program as the termination status of the process ). When a process terminates abnormally, the kernel will generate a termination state indicating the cause of its termination. Whether a process is terminated normally or abnormally, the parent process of the process can be obtained through the wait or waitpid function.
In the forkdemo. C and execdemo. C Programs in the previous two sections, the parent process after the fork call calls the sleep function to sleep. This is because, after the fork function is called, whether the parent process is executed first or the child process is executed first is uncertain. Therefore, we call sleep in the parent process to sleep for a period of time, so that the sub-process ends first (Note: This cannot be ensured ).
We can call wait in the parent process to wait for the child process to end,
# Include <sys/Wait. H>
Pid_t wait (int * statloc );
Returned value: if the process is successful, the process ID is returned. If an error occurs, the return value is-1.
The statloc parameter is an integer pointer. If statloc is not a null pointer, the termination status of the terminated process is stored in the memory unit pointed to by the pointer. If you do not care about the termination status, you can set the parameter to null.
When a process calls wait, the caller is blocked until a sub-process is terminated. If no sub-process is called when the wait function is called, an error is returned immediately.
Example:
The following program replaces the sleep statement of the parent process after fork with wait Based on execdemo. C in the previous section to wait for the completion of the Child process.
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <sys/wait.h>char sayhelloPath[] = "/home/lienhua34/program/c/apue/ch08/demo/sayhello";intmain(void){ pid_t pid; int waitres; if ((pid = fork()) < 0) { printf("fork error: %s\n", strerror(errno)); exit(-1); } else if (pid == 0) { printf("in child process, process ID: %d, parent process ID: %d\n", getpid(), getppid()); if (execv(sayhelloPath, NULL) < 0) { printf("execv error: %s\n", strerror(errno)); exit(-1); } } else { printf("in parent process, process ID: %d, child process ID: %d\n", getpid(), pid); if ((waitres = wait(NULL)) < 0) { printf("wait error: %s\n", strerror(errno)); exit(-1); } else { printf("termination child process: %d\n", waitres); } } exit(0);}
Compile the program, generate and execute the execdemo file,
lienhua34:demo$ gcc -o execdemo execdemo.clienhua34:demo$ ./execdemoin parent process, process ID: 3795, child process ID: 3796in child process, process ID: 3796, parent process ID: 3795Hello World! process ID: 3796termination child process: 3796
(Done)
Unix programming learning notes (18)-Process Management-Process Control Trilogy