Multi-process|Polling detection scheme based on non-blocking calls|Process waiting|Re-understanding hang|Linux OS


say up front

Today I will bring you the concept of process waiting in the operating system. The operating system we are learning is the Linux operating system.

Our main goal today is to understand the two system calls wait and waitpid .

foreword

那么这里博主先安利一下一些干货满满的专栏啦!

手撕数据结构https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014.3001.5482这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏https://blog.csdn.net/yu_cblog/category_11464817.html这里是STL源码剖析专栏,这个专栏将会持续更新STL各种容器的模拟实现。

STL源码剖析https://blog.csdn.net/yu_cblog/category_11983210.html?spm=1001.2014.3001.5482


what is process waiting

Simply put, process waiting is a state of a process, a process in which the parent process waits for the child process to exit.

Of course, if you describe it like this, everyone will definitely not understand it. If you continue to look back, I believe everyone will understand it!

Why do processes need to wait

First of all, we know that to create a child process, we must want the child process to complete something different from the parent process. Then when the child process is executed, if the parent process has not exited, the state of the child process is called a zombie .

  • The child process exits, the parent process does not care about the child process, the child process will be in a zombie state --- causing memory leaks
  • The parent process creates a child process to let the child process do things, so how does the child process complete the task? Does the parent process need to care? If so, how to know? If not, how to deal with it?

When the child process ends, there are three ways to end the child process:

  1. The subprocess code is executed and the result is correct
  2. The subprocess code is executed and the result is incorrect
  3. The subprocess code is not executed, and the program crashes

Then, if the parent process wants to perform different operations by judging the execution of the child process, our parent process must understand which of the above three types of execution the child process belongs to. At the same time, the parent process also needs to recycle the child process.

How to do process waiting

Process waiting has two system call interfaces:

  1. wait
  2. waitpid

wait

First, let's prepare the Makefile, myproc.c

Then, we first build a zombie state in myproc.c , and then we solve it through the system call interface that the process is waiting for.

As shown in the figure: build a zombie state through code.

In this code, after 5 seconds, the child process exits normally, and the child process at this time is in a Z state. 

For more detailed information about the wait function, we can obtain it through the manual.

 Usage of wait interface

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

The verification code and phenomenon are as follows:

waitpid 

The first parameter indicates the pid of the child process of the process to wait for.

When we first started learning code, there was generally only one parent process and one child process. But continue to learn later, when we come into contact with multiple processes, we have to use the waitpid interface to wait for the executing process.

The second parameter is an output parameter. We pass in the address of an int type variable status, and waitpid will store the execution status of the waiting process in status and bring it back.

The third parameter indicates the choice of blocking waiting mode/non-blocking waiting mode (we will explain and distinguish in detail later). 

At this point we can look at a simple example: 

Here we use blocking waiting as an example, that is, the third parameter is 0.

In the code, we let the child process return a special number, indicating its process exit code, here we pass 105

Finally, print the status (the code is not reflected, but the phenomenon is added to print the status, it is very simple, just add a sentence)

We found that the status is not 105 sent back.

This is because: status is not used in the form of integers, it is divided into bits in the form of status, a 32, we only learn the division of the lower 16 bit positions. 

First of all, we need to clarify a concept:
the exit code of the process is only meaningful when the process ends normally!

Suppose return 0 means normal exit, return 1 means segment fault, and exit() is the same. The premise of returning the exit code is that the program executes normally to this sentence. If the program exits abnormally, the exit code is meaningless. 

So how to judge whether the program exits abnormally? See if the received signal is 0

If the received signal is 0 -- the program exited normally.

Next is a question of C language -- how do we get the exit code and signal from the 32-bit integer status?

Here the blogger directly gave the result, if you don’t understand the partner, you should take a tutorial on the C language.

  • Exit code: (status>>8) & 0xFF
  • Signal: status & 0x7F

At this time, the blogger will once again emphasize this important concept for everyone 

 

Two important points:

  • The program exits abnormally. The essence is that the process exits abnormally. The essence is that the OS kills the process.
  • How to kill the OS - send a signal 

Examples of some programs exiting abnormally 

 

 

Having said that, let us answer three more questions: 

1. The parent process can get the exit result of the child process through wait/waitpid, why use the waitpid/wait function? Can't direct global variables??

Of course not, the process is independent, so the data must be copied on write, and the parent process must not be able to get it, let alone the signal.

2. Since the process is independent, isn’t the process exit code also the data of the child process? Why does the parent process get it? What does wait/waitpid do?

Here we have to start with the zombie process
Zombie process: at least the pcb information must be preserved! The exit result information when the process exits is retained in the task_struct!!

Therefore, the essence of wait/waitpid is to read the task_struct structure of the child process!

3. Now the question is: does wait/waitpid have this right???

​​​​​​​​Don’t forget , task_stuct is a kernel data structure object! Of course it has this right! Because they are system calls! Isn’t their work the OS work?

a small summary

waitpid/wait can make the process exit in a certain order under the current situation! In the future, the parent process can be allowed to do more finishing work!

some supplements

For those who use the upper layer, when I use it, I need to have a certain understanding of the operating system kernel and the composition of the status, so that I can extract information, which is too troublesome!

In fact, the operating system provides us with macros. At the beginning, the blogger didn’t tell everyone, but hoped that everyone could understand the low-level composition of status.

Blocking wait and non-blocking wait 

Therefore, if we call blocking wait, the state of the parent process before the end of the child process is, hang! 

re-understand hang

​​​​​​​​This blocking waiting is actually blocking in the system call interface (wait series functions), that is, blocking in the kernel

For example, if we used scanf and cin before, we didn't enter the keyboard. At this time, the OS finds that the resources in the buffer are not ready and the system suspends our process! At this time, on the surface, it is stuck!

And where is it stuck? From the von Neumann system, we know that the input hardware such as the keyboard, and the output hardware such as the monitor must pass through the operating system, so in fact, it is actually stuck in the kernel! scanf, cin must Encapsulates system calls!

The essence of blocking is to block in the kernel and suspend the process in the kernel!

Polling detection scheme based on non-blocking calls

Then when the non-blocking call is made, it returns directly, and the parent process does not wait.
Then how do we know the status of the sub-process? We will check the status of the sub-process every once in a while. If the end of the sub-process is detected, the sub-process will be released. This is called the polling detection scheme based on non-blocking calls.

 

 

Summarize 

I believe that after seeing this, everyone has a certain understanding of process waiting in the Linux operating system. Operating system learning is necessary, although it can be boring. If you find this article helpful, don't forget to click three times! !

Guess you like

Origin blog.csdn.net/Yu_Cblog/article/details/128751190