Linux: Process waiting

Process waiting

Process waiting refers to the parent process waiting for the child process to exit; in order to obtain the return value of the child process exiting; releasing all resources of the child process exiting; it can be seen that the process waiting is very important. As we said before, when the child process exits, if Regardless of the parent process, it may turn the child process into a zombie process and cause memory leaks. We also know that the zombie process is very difficult to deal with. Even kill-9 cannot "kill it", just like a person who becomes a zombie. For us, he is dead and cannot be killed a second time. And we want to know how the tasks assigned by the parent process to the child process are completed, for example, the child process has finished running, the result is correct or not, or whether it exits normally. At this point, we can reclaim the child process resources and obtain the exit information of the child process by letting the parent process wait through the process.

Two methods of process waiting

1.wait method`

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
 成功返回被等待进程pid,失败返回-1。(比如:没有退出子进程)
参数:
 输出型参数,获取子进程退出状态,不关心则可以设置成NULL

wait is a blocking interface that handles the exiting child process. Of course, if no child process exits, it will wait until there is a child process exit before calling the return

2.waitpid method

pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
 当正常返回的时候waitpid返回收集到的子进程的进程ID;
 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
 pid:
 Pid=-1,等待任一个子进程。与wait等效。
 Pid>0.等待其进程ID与pid相等的子进程。
 status:
 WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
 WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
 options:
 WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进
程的ID。

Note:
If the child process has exited, when wait/waitpid is called, wait/waitpid will return immediately, release the resources, and obtain the exit information of the child process.
If wait/waitpid is called at any time and the child process exists and is running normally, the process may be blocked.
If the child process does not exist, an error will be returned immediately.
Insert picture description here

Comparison of the two:
1. Wait waits for the exit of any child process (wait is a parent process, assuming there are not many child processes, any one exits, it will call and return after processing)
2. Waitpid can wait for the specified child process, or Wait for any child process, determined by the first parameter (the first parameter pid == -1 means waiting for any process)
3.wait is a blocking interface (if no child process exits, it will wait
forever ) 4.waitpid It can be blocked by default or non-blocking. It is determined by the third parameter (option == 0 means blocking by default) option == WNOHANG means non-blocking.
Note: Non-blocking operations generally require cyclic operations. You have to judge whether it can be processed until Responsible for the possibility of zombie processes until it succeeds.
For example

   #include <stdio.h>
   #include <stdlib.h>
   #include <unistd.h>
   #include <sys/wait.h>
  
   int main(int argc,char *argv[])
     {
    
    
       pid_t pid = fork();
       if(pid == 0)
      {
    
    
        sleep(5);
        exit(0);
     }
      else if(pid > 0)
      {
    
    
        int ret = waitpid(pid,NULL,WNOHANG);
        if(0 == ret)
        {
    
    
          printf("没有子进程退出!\n");                                          
        }
        while(1)
        {
    
    
          printf("正在打麻将!\n");
        }
     }
      return 0;
    }

Run this program at this time and use the ps aux | grep command to check that the child process has become a zombie process
Insert picture description here

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
 
int main(int argc, char *argv[])                                                                                                                            
{
    
    
   pid_t pid = fork();
   if(0 == pid)
   {
    
    
     sleep(5);
     exit(0);
   }
   else if(pid > 0)
   {
    
    
     int status;
     while(waitpid(pid,&status,WNOHANG)== 0){
    
    
       printf("没有子进程退出,再等等!");
       sleep(1);
     }
     while(1)
     {
    
    
       printf("正在打麻将!\n");
       sleep(1);
     }
   }
   return 0;
 }

This problem is solved after using loop processing
Insert picture description here

Get child process status

Whether it is wait or waitpid, there is a status parameter. This parameter is an output parameter, which is filled by the operating system. If NULL is passed, it means that the retirement status of the child process is not cared about. Otherwise, the operating system will change the child process according to this parameter. The exit information of the process is fed back to the parent process. Status cannot be simply treated as a plastic shape, but can be treated as a bitmap. The details are as follows (only the low 16 bits of status are studied
):
Insert picture description here

In the foregoing, we have two scenarios until a process exits: normal exit and abnormal exit.
When a process exits normally, the return value is meaningful, otherwise the return value is meaningless. Therefore, before obtaining the return value, you should first pass the lower 7 bits to determine whether the process exits normally (normal exit, the abnormal exit signal is 0; otherwise, it is greater than 0),
Insert picture description here
so the method to determine whether a process exits normally is: take out the lower 7 Bit

status & 0x7f == 0 正常退出
0x7f == 0111 1111

Then take out the high eight bits of the low 16 bits

(status >> 8) & 0xff

This is the status we want to get.
Code:

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main( void )
{
    
    
 	pid_t pid;
 	if ( (pid=fork()) == -1 )
 	perror("fork"),exit(1);
	if ( pid == 0 ){
    
    
	sleep(20);
	exit(10);
 } else 
 {
    
    
 	int st;
 	int ret = wait(&st);
 
 	if ( ret > 0 && ( st & 0X7F ) == 0 ){
    
     // 正常退出
	 printf("child exit code:%d\n", (st>>8)&0XFF);
 } else if( ret > 0 ) {
    
     // 异常退出
	 printf("sig code : %d\n", st&0X7F );
	 }
 	}
}

Operation result: The
Insert picture description here
above result is run twice, and then compare the results of killing the process in other middle ends. The above is the result of the kill operation, and the bottom is the result of the kill operation. If it is 9 No. command, then the result is sig code: 9

Guess you like

Origin blog.csdn.net/qq_43825377/article/details/113826404