[C/C ++] multi-process: the parent process listens to the use of the sub-process status wait () and listens to the wait
Article structure:
- Wait capability Introduction
- Wait () function description
- DEMO code and Operation
Wait capability Introduction
In the previous article [C/C ++] multi-process: creating a sub-process fork (), we demonstrated the creation of a sub-process.
After a child process is created, the parent process can monitor the running status of the child process. The functions used are as follows:
#include <sys/wait.h> pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status, int options);
The preceding functions are used to wait for the callback of the sub-process status change and obtain the status change information. Possible status changes include: the sub-process stops running, the sub-process is paused by the semaphore, and the sub-process is resumed by the semaphore.
The parent process is executed.wait
After the function, if the sub-process has changed its statuswait
The function returns results immediately. Otherwisewait
The function is blocked until the sub-process status changes.
Generally, if the sub-process has changed its status but has not been executed by the parent process or other system callbackswait
The sub-process is called waitable ).
After the sub-process ends, the parent executeswait
A function can push the system to release resources related to sub-processes; otherwise, sub-processes will be maintained inBotnets
.
Wait () function description
Functionwait(int * status)
Yeswaitpid()
Only when any sub-process stops running. Otherwise, the called process is blocked and paused.wait(int * status)
Equivalent to the following code:
waitpid(-1, &status, 0);
waitpid()
The call process will be blocked until the running status of any sub-process changes. Nextwaitpid()
The three parameters are described as follows:
pid < -1
Take the absolute value of the pid. If the process group ID of any sub-process is equal to the absolute value, changes in the Process status of any sub-process in the group will triggerwaitpid()
.
pid == -1
The listening scope is extended to any sub-process.
pid == 0
The ID of the process group where the listener is restricted to sub-processes is equal to that of the parent process.
pid > 0
The ID of the specified sub-process.
The value can beNULL
. When notNULL
Is used to store the information value that triggers the status change andexit(code)
Incode
Value.
wait.h
The header file defines several macros for parsing.status
Common values include:
Macro |
Description |
WIFEXITED (status)
WEXITSTATUS (status)
|
When a sub-process callsexit(code) Or_exit(code) Or runmain() Returnstrue .
WhenWIFEXITED(status) Istrue Obtainexit(code) Or_exit(code) Ofcode Value. Wherecode It can only be 0 or positive. Negative numbers are not supported. |
WIFSIGNALED (status)
WTERMSIG (status) |
Returned when the child process is killed by a semaphoretrue .
WhenWIFSIGNALED(status) Istrue To obtain the semaphore value. |
WIFSTOPPED (status)
WSTOPSIG (status) |
Returned when the sub-process is paused by the semaphoretrue .
WhenWIFSTOPPED(status) Istrue To obtain the semaphore value. |
The value can be any value of the following constant or any constant and zeroOR
Calculate the value.
Constant |
Description |
WNOHANG |
Callwait Specifiedpid If the operation is still not completedwait Returns 0 immediately. |
WUNTRACED |
When the sub-process is pausedwait Returnspid . |
WCONTINUED
|
When the paused sub-process is restored by the semaphorewait Returnspid . Linux 2.6.10 and later. It does not take effect on Mac 0 s x 10.9.5. |
wait()
The function returnspid
Value. If an error occurs during execution,-1 is returned.
waitpid()
When a function is executed normally, it returns a process whose status changes.pid
Value; if the function options containsWNOHANG
Constantpid
If the sub-process has not exited and the Process status has not changed, return 0 directly. If the sub-process has exited, return the sub-process'spid
Otherwise,-1 is returned when an error occurs.
DEMO code and Operation
Due to the two processes involved, log printing on the terminal command line may be messy, so the logs of the two processes are output to two files by redirecting the standard input/output stream, logs of the parent process are outputmain.txt
Sub-process logs are outputchild.txt
. This involves redirecting standard input/output streams. For details, see [C/C ++] File Creation, opening, reading, writing, copying, closing, deleting, and other operations.
Involvedps
,kill
You can useman ps
Andman kill
Search for details.
The following code will demonstratefork()
After a sub-process passesps
Command to query the Process status andkill
Command to send a semaphore to the sub-process to change the process status; the parent process passeswait
Listen to the sub-process status.
wait.c
The source code is as follows:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
# Include <sys/wait. h> # include <errno. h> # include <stdlib. h> # include <string. h> # include <unistd. h> # include <stdio. h> # include <time. h> # ifndef CHILD_COUNT # define CHILD_COUNT 10000 # endifstatic void printTime () {time_t calendar_time = time (NULL); struct tm * tm_local = localtime (& calendar_time ); char str_f_t [50]; strftime (str_f_t, sizeof (str_f_t), "% G-% m-% d % H: % M: % S", tm_local ); printf ("% s", str_f_t);} int main/* 09 */(int argc, char * argv []) {pid_t cpid, w; int status; cpid = fork (); if (cpid =-1) {perror ("fork"); exit (EXIT_FAILURE);} if (cpid = 0) {/* Code executed by child */FILE * fChild = freopen ("/Users/sodino/workspace/xcode/Define/child.txt", "w", stdout ); printTime (); printf ("Child PID is % ld argc = % d \ n", (long) getpid (), argc); int count = 0; do {sleep (1); printTime (); printf ("sleep count = % d \ n", count); fflush (fChild); count ++; if (count> CHILD_COUNT) {break;} while (1); fflush (fChild); fclose (fChild); // The code value will be from the parent process's WEXITSTATUS () in macro definition, learn // _ exit (123); exit (123 );} else {FILE * fMain = freopen ("/Users/sodino/workspace/xcode/Define/main.txt", "w", stdout); // If the sub-process is still running, 0 is returned. if the sub-process has completed running, the sub-process pid w = waitpid (cpid, & status, WNOHANG) is returned; if (w = 0) {printTime (); printf ("Child PID = % d has not yet changed state \ n", cpid);} else {printTime (); printf ("Child PID = % d has been terminated. \ n ", cpid);} int ifExited, ifSignaled, ifStopped, ifContinued;/* Code executed by parent */do {// invalid on mac · WCONTINUED, from the perspective of the file, it only applies to thread w = waitpid (cpid, & status, WUNTRACED | WCONTINUED); // w = waitpid (cpid, & status, WUNTRACED ); if (w =-1) {printTime (); printf ("Parent w =-1, error = % s \ n", strerror (errno )); exit (EXIT_FAILURE);} if (w = 0) {printTime (); printf ("w = 0 ignore. continue. \ n "); continue;} ifExited = WIFEXITED (status); ifSignaled = WIFSIGNALED (status); ifStopped = WIFSTOPPED (status); ifContinued = WIFCONTINUED (status); printTime (); printf ("pid = % ld w = % d exitCode = % d status = % d ifExited = % d ifSignaled = % d ifStopped = % d ifContinued = % d \ n ", (long) getpid (), // w, status, WEXITSTATUS (w), ifExited, ifSignaled, ifStopped, ifContinued); w, status, _ WSTATUS (w), ifExited, ifSignaled, ifStopped, ifContinued); printTime (); if (ifExited) {printf ("PID = % ld exited, status = % d \ n", (long) w, WEXITSTATUS (status);} else if (ifSignaled) {printf ("PID = % ld killed by signal % d \ n", (long) w, WTERMSIG (status);} else if (ifStopped) {printf ("PID = % ld stopped by signal % d \ n", (long) w, WSTOPSIG (status);} else if (ifContinued) {printf ("PID = % ld continued \ n", (long) w);} fflush (fMain ); if (ifExited | ifSignaled) {printTime (); printf ("isExited = % d isSingaled = % d \ n", ifExited, ifSignaled); fflush (fMain ); break ;}} while (1); printTime (); printf ("Main PID % ld exit. \ n ", (long) getpid (); fclose (fMain); exit (EXIT_SUCCESS );}} |
Gowait.c
To compile and run the following command:
Gcc wait. c // generate the executable file a. out./a. out // run the executable file
Useps -j
Command to view the process.fork()
After the process is executed, there are two names in the Process List:a.out
. For example:
We can see that the parent process of PID = 678 is PID = 677. The PGID of both processes is 677.
WatchingSTAT
Column, both processes areS+
, WhereS
Indicates that the process is insleeping
Status because the parent process is inwait
In addition to printing logs, sub-processes are running most of the time.sleep()
; Another+
Indicates that both processes are in the foreground of the current console.
Connect to usekill -SIGSTOP 678
Command to send a pause signal to the sub-process, and thenps -j
Check the Process status and find that the sub-process 678 has beenS+
ChangeT+
Is in the STOP status.
On the other hand, Viewchild.txt
The file will no longer generate logs. Viewmain.txt
File. The log content is as follows:
2015-04-16 22:53:15 Child PID=678 has not yet changed state 2015-04-16 23:11:48 pid=677 w=678 exitCode=4479 status=38 ifExited=0 ifSignaled=0 ifStopped=1 ifContinued=0 2015-04-16 23:11:48 PID=678 stopped by signal 17
First sentenceChild PID=678 has not yet changed state
Yesparent Process Executionwaitpid:WNOHANG
The returned result indicates that the sub-process has not exited and is running. The second sentence is output.ifStopped=1
Indicateswaitpid:WUNTRACED
The system has monitored the semaphore sent by the sub-process to change the process status. Third sentencePID=678 stopped by signal 17
Indicates that the signal value is 17. The following command may verify that the SIGSTOP signal value is 17:
sodino:Define sodino$ kill -l SIGSTOP 17
Next, continue to usekill -SIGCONT 678
Command to restore the sub-process running, see:
The sub-process resumes running from the stopped status. Viewchild.txt
The log returns the output again:
... ... 2015-04-16 23:11:46 sleep count=1110 2015-04-16 23:11:47 sleep count=1111 2015-04-16 23:23:20 sleep count=1112 2015-04-16 23:23:21 sleep count=1113 ... ...
Note that the Process status is stopped during the period from to, so no log output is available (you can write a blog during this period of time ..). Viewmain.txt
Nowaitpid
I personally think this is a problem with the C version and runtime environment on my mac.
Finally, use the commandkill -SIGTERM 678
You can findps
The command cannot be found.a.out
Process.
Viewmain.txt
We can find thatwaitpid
With the return valueifSignaled=1
Indicates that the sub-process has been semaphores15
Killed. And finally quit.
2015-04-16 23:31:00 pid=677 w=678 exitCode=15 status=38 ifExited=0 ifSignaled=1 ifStopped=0 ifContinued=0 2015-04-16 23:31:00 PID=678 killed by signal 15 2015-04-16 23:31:00 isExited=0 isSingaled=1 2015-04-16 23:31:00 Main PID 677 exit.
The above is what I want to talk about in this article. Next: multi-process: Zombie Process