Linux System Programming 44 Signal-Analysis of the response process of the signal! ! !

Signal unreliability :
refers to the unreliable behavior of the signal, because the execution scene is not arranged by us, but arranged by the kernel, so it is possible that the second call will occur before the first call is over.

Reentrant function : It is to solve the unreliability of
the signal. When the first call has not ended, the second call occurs, but there is no error. Such a function is called a reentrant function. All system calls are reentrant, and some library functions are also reentrant, such as memcpy().

The kernel maintains two bitmaps for each process:
signal mask mask : used to indicate the state of the current signal, the initial value of the mask is generally all 1
pending bitmap : used to record which signals the current process receives, generally initial Values ​​are all 0

Thinking:
1. There is an inevitable delay from signal reception to response.
2. How to ignore a signal.
3. Why should standard signals be lost.
4. There is no strict order for the response of standard signals.

5. The signal processing function cannot jump outside (setjmp. longjmp)

Take the experiment in the above section as an example to analyze the response process of the signal:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sig_handler(int s)
{
	write(1,"!",1);
}

int main()
{
	int i;

	signal(SIGINT,sig_handler);

	for(i=0 ; i<12 ; i++)
	{
		write(1,"*",1);
		sleep(1);
	}

	exit(0);
}

Insert picture description here

The first step: the
program runs, when the time slice of the program is exhausted (it can also be understood as an interrupt signal sent to itself in some form), the program saves the current process state (including the program execution position, used to return to the previous state) to Kernel mode, mounted to the waiting queue waiting for ready in the kernel, waiting to obtain the time slice, that is, waiting to be scheduled to itself, after scheduling to itself, return to the user mode with the saved process state, at this time the time to switch from the kernel mode to the user mode The point is very important. At this moment, a job will be done: the mask bitmap is bitmap and pending bitmap to determine whether a signal is received. If calculated according to the initial state of the two bitmaps, the bitmap and the following are 0, which means there is no signal. . Only then will it return to the address of the previous program execution to continue executing the previous program.

Step 2:
Execute CTRL+C from the terminal to send a SIGINT termination signal to the program. At this time, the pending bitmap SIGINT signal is set to 1, indicating that the current program has received the SIGINT signal. But the program cannot respond to the SIGINT signal at this time, why? Because the program will have an inevitable delay from receiving the signal to responding to the signal, it is known from the first step that only when the program switches from the kernel mode to the user mode, the mask bitmap and the pending bitmap will be compared. Only at this time In order to know whether a signal has been received, which signal has been received, and will respond to the signal.

The third step: the
program time slice is exhausted again (it can also be understood as an interrupt signal sent to itself in some form), the program saves the current program state again and enters the kernel state, mounts to the dispatch queue and waits to be dispatched. The program is scheduled again, gets the time slice, and switches from the kernel mode to the user mode. At this time, at this time, the program will compare the mask bitmap with the pending bitmap, and perform a bitwise AND operation to determine whether it has received it. Signal, it is found that the SIGINT bit of the pending bitmap is 1, it indicates that the SIGINT signal is received, so it is ready to respond to the SIGINT signal, that is, the signal response program is executed. At this time, the program will not return to the previously executed address, but will go to the address of the previously registered signal response function to perform the signal response, that is, the address information in the saved program information will be changed to the address of the signal response function, at this time mask The SIGINT signal bit of the bitmap and pending bitmap will be set to 0. After executing the response program, return to the kernel mode again, and set the SIGINT of the mask bitmap to 1. And change the saved address information back to the previous execution address, switch from the kernel mode to the user mode again, and compare the mask bitmap with the pengding bitmap again. If the SIGINT signal is not received again during this period, the comparison result is 0 at this time, that is, it is found that no new SIGINT signal has been received, and the signals of other bits are the same, and then the previous program will continue to be executed, that is, print*

So the question to think about:

1 There is an unavoidable delay from receiving the signal to the response. It
can be understood that the signal is the response of the program from the kernel mode to the user mode, and can only respond at this point in time. So this delay is the time that the program must switch from the kernel mode to the user mode again, that is, there must be a new interrupt or the time slice is exhausted, the program enters the kernel mode and waits for the time required for switching back to the user mode after scheduling, so if the program After receiving the signal, there has been no interruption to interrupt him, or the time slice has not been exhausted, that is, it has not entered the kernel mode, and it cannot be switched from the kernel mode to the user mode, and the two bitmaps cannot be compared. Find the signal.

In a word, the signal is the response of the program from the kernel mode back to the user mode.

2 How to ignore a signal
From the signal response process above, we can know that as long as the corresponding signal bit in the mask bitmap is always set to 0. In this way, even if the corresponding signal is received, after the two bitmaps are compared, the result is also 0, that is, no signal.

3 Why is the standard signal lost? When the
program responds to the signal, the mask bitmap and the corresponding signal bit of the pending bitmap will be set to 0. At this time, if the SIGINT signal is sent 10,000 times, the result is only the pending bitmap. The SIGINT signal is set to 1 10,000 times repeatedly, and the result is still 1. That is, when the program finishes executing the signal response and switches back to the user mode, the SIGINT bit of the mask bitmap is reset to 1, and when the two bitmaps are compared again, although the SIGINT signal is received 10,000 times, it only knows the last reception. To the signal.

4 There is no strict order for the response of standard signals

5 You can’t jump from the signal processing function randomly. It
can be seen that the program switches from the kernel mode to the user mode, and the mask bitmap and pending bitmap changes are found, so the kernel replaces the execution program address to execute the signal response program, and the mask The signal shielding position is 0. After the response program is executed, the kernel is re-cored again, and the mask signal shielding position is 1 again, that is, the signal shielding word is unblocked, so that the signal can be received normally later, and finally back to the user state. If you jump to other positions in the signal response program, you will miss the unblocking operation of the signal shielding word, and you will not be able to respond to the corresponding signal in the future.
So setjmp() and longjmp() should be used with caution in signal processing functions.

In this process, when the program responds to the signal, the mask bitmap is set to 0 in order to prevent reentry, which will be supplemented in detail later.

Guess you like

Origin blog.csdn.net/LinuxArmbiggod/article/details/114004435