[Linux] Process waiting




tips

The following code can loop to detect the process.

while :; do ps ajx | head -1; ps ajx | grep testwait | grep -v grep; sleep 1; echo "-------------------------------------"; done

1. What is process waiting?

Through the system call wait/waitpid, the status of the child process is detected and recycled.

2. Why is there a process waiting?

  • 1. The zombie process cannot be killed. It needs to be killed by waiting for the process to solve the problem of memory leaks. ——This must be solved.
  • 2. It is necessary to wait through the process to obtain the exit status of the child process. That is, I want to know how it is doing on the tasks assigned to it. ——This is optional.

The focus of process waiting is to solve the above two problems.

3. How to wait for the process?

Let’s first look at what process waiting is

  7 int main()
  8 {
    
    
  9 
 10      pid_t id = fork();
 11      if(id < 0)
 12      {
    
    
 13          perror("fork");
 14          return 0;
 15      }
 16      else if(id == 0)
 17      {
    
    
 18          //child
 19          int cnt = 5;
 20          while(cnt)
 21          {
    
    
 22              printf("I am child,pid : %d , ppid : %d\n",getpid(),getppid());
 23              sleep(1);
 24              cnt--;
 25          }
 26 
 27          exit(0);
 28      }
 29      else
 30      {
    
                                                                                                                                                                                         
 31          //parent
 32          int cnt = 10;
 33          while(cnt)
 34          {
    
    
 35              printf("I am parent,pid : %d , ppid : %d\n",getpid(),getppid());
 36              sleep(1);
 37              cnt--;
 38          }
 39 
 40          pid_t ret = wait(NULL);
 41          if(ret == id)
 42          {
    
    
 43              printf("wait success,ret = %d\n",ret);
 44          }
 45 
 46          sleep(5);
 47      }
 48 }

The meaning of the above code is:
First create a child process, and the parent and child processes run at the same time for 5 seconds. The first 5 seconds are in the blocked state, that is, the S state.
The child process exits in the middle 5 seconds and waits for the parent process to recycle. At this time, the child process becomes a zombie state, that is, Z state.
In the next 5 seconds, the parent process waits for the child process to exit through wait, and then recycles the child process. At this time, only the parent process is still running.
Then the parent process also exits.

Insert image description here

The following is a loop to create 10 child processes:

  7 void Runchild()
  8 {
    
    
  9     int cnt = 5;
 10     while(cnt)
 11     {
    
    
 12         printf("i am child, pid : %d,ppid : %d\n",getpid(),getppid());
 13         sleep(1);
 14         cnt--;
 15     }
 16 }
 17 
 18 int main()
 19 {
    
    
 20     int i = 0;
 21     //创建10个子进程
 22     for(;i<10;i++)
 23     {
    
    
 24         pid_t id = fork();
 25         if(id == 0)
 26         {
    
    
 27             Runchild();
 28             exit(0);
 29         }
 30     }
 31 
 32     sleep(10);
 33 
 34     //目前来说,进程等待是必须的
 35     for(i=0;i<10;i++)                                                                                                                                                                      
 36     {
    
    
 37         pid_t ret = wait(NULL);
 38         printf("wait success: %d\n",ret);
 39     }
 40 
 41     sleep(5);
 42     return 0;
 43 }

executes the code in the first 5 seconds, creates 10 child processes, and the parent and child processes run at the same time.
In the middle 5 seconds, 10 child processes exited and became zombies, waiting for the parent process to recycle
In the next 5 seconds, the parent process called the wait system call 10 times. 10 zombie processes are recycled.
After 5 seconds of recycling, the parent process exits.

Summary: Currently, process waiting is necessary in order to kill the zombie state, recycle resources, and prevent memory leaks.


Question 1:
What if the parent process has been waiting for the child process, but the child process never exits?

If the parent process cannot wait for the child process to exit, the parent process will keep waiting. If wait does not return a result, the parent process will remain blocked.

wait and waitpid

Insert image description here

status parameter

The wait function only needs to pass in one parameter: status, which represents the exit status of the process. Generally, it is an integer. The integer is 32 bits, and generally only the lower 16 bits are considered.

Insert image description here

Among them, exiting the core dump will be discussed later. The exit signal of the process can be queried:

Through the kill -l command, we found that there are 64 exit signals, represented by 0~7 bits of the status variable.

Insert image description here

The exit code of the process is represented by 8~15 bits.
Insert image description here

Among them, 0 means that the process is running normally and the result is correct.


Question: Can you create a global variable status yourself? When the child process exits, set the status variable to a different exit code, representing different exit statuses and return it to the parent process?

The answer is impossible. **Because the parent and child processes are independent. **When the child process wants to modify the status, copy-on-write will occur. The resources of the parent and child processes are independent of each other. The status returned by the child process cannot be obtained by the parent process. Therefore, the operating system can only use system calls to help the parent process obtain the status from the child process. Get resources in the process.

Wait for the child process through the parent process, pass the status parameter into waitpid, and obtain the exit information and exit code of the child process.

if(id > 0)
{
    
    
	int status=0; // 低16位有效
	pid_t ret = waitpid(id,&status,0);
	if(ret == id)
	{
    
    
	    //低七位是退出信号,次低八位是退出码
	    printf("wait success! id = %d , exit sig = %d, exit code = %d\n",ret,status&0x7F,(status>>8)&0xFF);
	}
}

The core code is as above:

status&0x7F, you can get the exit signal of the child process
Insert image description here
Get the exit code of the child process through the second-lowest 8 bits of status.
(status>>8)&0xFF

In fact, the library also provides two macros to replace the above stauts&0x7F, and (status>>8)&0xFF

  • 1.WIFEXITED(status): True if it is the status returned by the normal termination of the child process. (Check whether the process exited normally) - It is equivalent to adding status&0x7F and a logical inversion.

  • 2.WEXITSTATUS(status): If WIFEXITED is non-zero, extract the child process exit code. (View the exit code of the process) - equivalent to(status>>8)&0xFF

 if(ret == id)
 {
    
    
     //低七位是退出信号,次低八位是退出码
     //printf("wait success! id = %d , exit sig = %d, exit code = %d\n",ret,status&0x7F,(status>>8)&0xFF);
     if(WIFEXITED(status))
     {
    
    
         printf("父进程等待它的子进程成功,退出码为:%d\n",WEXITSTATUS(status));
     }
 }
 else
 {
    
    
     printf("父进程等待它的子进程失败!\n");
 }

The core code is as above. Entering if means that the parent process is waiting for the success of its child process.
Enter else, indicating that the parent process is not waiting for its own child process.

Therefore, the parent process will only succeed if it waits for the child process it created.


Summarize:

  • 1. As long as the low 7 bits of the wait/waitpid function's status parameter are judged to be 0, you can know whether the process has finished running.
  • 2. As long as you judge the exit code of the process through 8 to 15 digits, you will know the results of the process.

This corresponds to the fact that there are only three exit situations for a process:

  • 1. The process exits normally and the result is correct
  • 2. The process exits normally, but the result is incorrect.
  • 3. The process exits abnormally

From then on, you can wait for the corresponding process through waitpid, and then obtain the exit status of the corresponding process.

options parameter

The options parameter means to let the parent process choose how to wait for the child process to exit!

There are two waiting methods provided below, blocking waiting and non-blocking waiting!

non-blocking polling

WNOHANG: If the child process specified by pid has not ended, the waitpid() function returns 0 and does not wait. If it ends normally, the ID of the child process is returned.

WNOHANG is a macro, which means non-blocking waiting.

Let’s first talk about what polling is:

The final exam is coming soon. Xiao Wu is a hard-working academic, and Xiao Deng is a poor academic. The teacher said: There will be a C language test tomorrow!
When Xiao Deng heard this, he immediately panicked. He called Xiao Wu immediately after class and said to Xiao Wu: "Xiao Wu, can I borrow your notes and you? ”
Xiao Wu knew right away that Xiao Deng wanted me to teach him!
Xiao Wu said: "Okay, wait a minute, I am reviewing, and I will go down to find you later."
Xiao Deng hung up the phone after hearing this. After 10 seconds, Xiao Deng called Xiao Wu again: "Are you okay?"
Xiao Wu said: "Not yet." With a bang, Xiao Deng hung up the phone. . After another ten seconds, he called Xiao Wu again: "Are you okay?" "Not yet." Just like that, after making more than 20 calls, Xiao Wu said: "Okay, I'll go down to find you now."

This process of Xiao Deng calling Xiao Wu to ask about the situation every once in a while is calledpolling!!!

And what is non-blocking polling?

As Xiao Deng kept calling Xiao Wu to ask about the situation, Xiao Deng learned to be smart. Waiting was not an option, so Xiao Deng was reading a C language textbook while reading. wait. It means that Xiao Deng can do his own thingwhile waiting! ! !

This means non-blocking! ! !

So, the combination of the two isnon-blocking polling! ! !

Xiao Wu is equivalent to the operating system, and Xiao Deng is equivalent to the parent process. The parent process is constantly asking the operating system and waiting for the result to be returned, which is the process of polling.
The parent process can do its own thing during polling, which is called non-blocking polling! ! !

Summary: WNOHANG waiting mode is a non-blocking waiting mode. If the waiting child process does not end, 0 will be returned. If the waiting is successful, the id of the child process will be returned.

int main()
{
    
    
    pid_t id = fork();

    if(id < 0)
    {
    
    
        perror("fork");
        exit(0);
    }
    else if(id == 0)
    {
    
    
        //child
        int cnt = 10;
        // int a = 10;
        // a/=0;
        while(cnt--)
        {
    
    
            printf("i am a child, pid %d, ppid %d \n",getpid(),getppid());
            sleep(1);
        }
        exit(11);
    }
    else 
    {
    
    
        //parent
        int cnt = 5;
        while(cnt--)
        {
    
    
            printf("i am a parent, pid %d, ppid %d \n",getpid(),getppid());
            sleep(1);
        }

        while(1)  //轮询
        {
    
    
            int status=0; // 低16位有效
            pid_t ret = waitpid(id,&status,WNOHANG); //非阻塞等待
            //pid_t ret = waitpid(id,&status,0); //阻塞等待
            //阻塞等待,父进程什么都做不了,只能在这里死等着子进程

            if(ret < 0) //等待失败
            {
    
       
                printf("等待子进程失败!\n");
                break;
            }

            //等待成功
            else if(ret > 0)
            {
    
    
                //低七位是退出信号,次低八位是退出码
                //printf("wait success! id = %d , exit sig = %d, exit code = %d\n",ret,status&0x7F,(status>>8)&0xFF);
                if(WIFEXITED(status))
                {
    
    
                    printf("父进程等待它的子进程成功,退出码为:%d\n",WEXITSTATUS(status));
                }
                break;
            }

            else
            {
    
    
                printf("子进程还未退出,再等等....\n");
                //等的过程父进程可以做自己的事情
                int a = 10;
                int b = 20;
                int c = a+b;
                printf("父进程在进行相加运算,结果为:%d\n",c);
            }

            //每隔1秒等待1次
            sleep(1);
        }
        
    }
    return 0;
}
pid_t ret = waitpid(id,&status,WNOHANG); 

This code means that the parent process uses non-blocking waiting when waiting for the child processNon-blocking waiting (WNOHANG)
Continuously executing the while loop is polling.

pid_t ret = waitpid(id,&status,0); 

This code is blocking waiting. If the child process does not exit, the parent process will wait here stupidly for the child process to exit. I can't do anything myself.

The principle of process waiting

The parent process calls the waitpid system call provided by the operating system, and then the operating system receives the application from the parent process to query the status of the child process corresponding to the parent process.
If the child process is in the s state, the operating system will return the status result of the child process to the parent process.
If the child process is in the z state, the operating system will take out the exit code exit_code and exit signal exit_signal of the child process and return them to the parent process. After the parent process receives the information, it knows what to do next.

Insert image description here


Question: Why doesn’t the parent process directly go to the child process to obtain the running status of the child process?

Because the operating system doesn't trust anyone!!!

For example: There is a student from school A who is very good at cyberspace security. The principal of school B wants to invite the student from school A to help school B participate in a cyberspace security competition. Principal B directly Find the student from school A and ask him to participate in the competition.
This cannot be done, because if Principal B wants to find students from School A, he has to ask Principal A! ! !

The same is true for the operating system for the parent process. The parent process cannot directly obtain the data of the child process, it must go through the medium of the operating system! ! !

Because what if the parent process modifies the data of the child process? ? ?

So, the operating system doesn't trust anyone! ! !

Summarize

This article details the various details of process waiting.

Guess you like

Origin blog.csdn.net/w2915w/article/details/134306363