process signal two
1. Preservation of signals
1. Other common concepts related to signals
- The actual execution of the signal processing action is called the signal delivery (Delivery)
- The state between signal generation and delivery is called signal pending (Pending) .
A process can choose to block (Block) a signal. When a blocked signal is generated, it will remain in a pending state until the process unblocks the signal before performing the delivery action.
Note: blocking and ignoring are different, as long as the signal is blocked, it will not be delivered, while ignoring is an optional processing action after delivery .
2. The signal is represented in the kernel
Schematic representation of signals in the kernel:
There are three tables in the operating system kernel, two are bitmap structures ( block
and pending
), and one is a function pointer array structure.
-
block
Table: Whether the bit at the corresponding position in the bitmap structure is1
, represents whether the signal is blocked. -
pending
Table: Whether the bit at the corresponding position in the bitmap structure is1
, represents whether the signal is pending. -
handler
Table: The table stores function pointers, and the function pointer in the corresponding subscript indicates which function to call when receiving the signal.
(In the entire three tables, the data is logically transferred horizontally)
The signal inside SIG_DFL
means to execute the default action, and SIG_IGN
means to execute the ignore action. They are defined as follows:
The principle of the function we used before signal
is to modify handler
the function pointer at the corresponding position in the table.
explain:
-
Each signal has two flags indicating blocking (block) and pending (pending) , and a function pointer indicating processing actions. When a signal is generated, the kernel sets the pending flag of the signal in the process control block, and the flag is not cleared until the signal is delivered. In the example above,
SIGHUP
the signal is neither blocked nor generated, and the default processing action is performed when it is delivered. -
SIGINT
The signal has been generated, but is being blocked, so it cannot be delivered temporarily. Although its processing action is to ignore, this signal cannot be ignored before unblocking, because the process still has the opportunity to change the processing action before unblocking. -
SIGQUIT
The signal has not been generated, and onceSIGQUIT
the signal is generated, it will be blocked, and its processing action is a user-defined functionsighandler
.
What to do if a signal is generated multiple times before the process unblocks it?
POSIX.1 allows the system to deliver this signal one or more times. Linux is implemented in this way: regular signals are generated multiple times before delivery and only counted once , while real-time signals are generated multiple times before delivery and can be placed in a queue in turn.
3. Signal set in the system kernel
From the schematic representation of the signal in the kernel: each signal has only one bit pending flag, which is either 0 or 1, and the number of times the signal has been generated is not recorded, and the blocking flag is also represented in this way.
sigset_t
Therefore, the pending and blocked flags can be stored with the same data type sigset_t
, called a signal set. The essence of this type is a bitmap structure, which can represent the "valid" or "invalid" status of each signal. In the blocking signal The meaning of "active" and "inactive" in the set is whether the signal is blocked, while the meaning of "active" and "inactive" in the pending signal set is whether the signal is pending. The blocking signal set is also called the signal mask of the current process (Signal Mask) , and the "shielding" here should be understood as blocking rather than ignoring.
Introduction to sigset_t type
sigset_t
It is Linux
a data type provided to us by the operating system. Its underlying package is an long
array of types. We use each bit in this array to represent relevant information.
2. Signal set operation function
1. The operation function of sigset_t type
sigset_t
The type uses a bit for each signal to indicate the "valid" or "invalid" status. As for how to store these bits inside this type, it depends on the system implementation. From the user's point of view, it does not need to be concerned. The user can only call the following functions to Manipulate sigset_ t
variables instead of directly manipulating its internal data.
-
The function
sigemptyset
initializes the signal set pointed to by set, and clears the corresponding bits of all signals in it, indicating that the signal set does not contain any valid signals. -
The function
sigfillset
initializes the signal set pointed to by set, and sets the corresponding bits of all signals in it1
, indicating that the effective signals of this signal set include all signals supported by the system. -
The function is to set the bit position corresponding to
sigaddset
the signal in the signal set pointed to by set assignum
1
-
The function is to set the bit position corresponding to
sigdelset
the signal in the signal set pointed to by set assignum
0
-
sigismember
It is a Boolean function used to judge whether a signal set contains the signum signal, if it is included, it will return 1, if it is not included, it will return 0, and if it fails, it will return -1. -
Note, before using
sigset_ t
the variable of the type, it must be calledsigemptyset
orsigfillset
initialized to make the signal set in a definite state. After the variable is initialized , it is possible to add or remove some valid signalsigset_t
in the callsigaddset
and in the signal set.sigdelset
-
These four functions all return successfully
0
and return on error-1
2. System calls about block tables
sigprocmask
The calling function can read or change the signal mask (blocking signal set) of the process.
-
Parameters :
-
The first parameter is a flag bit, which has the following three options to choose from:
(assuming the current signal mask is mask)
parameter | Function |
---|---|
SIG_BLOCK | set contains the signal we want to add to the current signal mask, which is equivalent to mask = mask | set |
SIG_UNBLOCK | set contains the signals we want to unblock from the current signal mask, equivalent to mask=mask&~set |
SIG_SETMASK | Set the current signal mask word to the value pointed to by set, which is equivalent to mask=set |
-
The second parameter is a signal set.
-
The third signal is an output parameter. When the system
block
sets a new signal set for the signal set, the content of the old signal set will be extracted and copied intooldset
it. -
Return value : Return if the call is successful
0
, return if the call fails-1
, and the error code is set.
For blocked signals, if the blocking is unblocked, it will be delivered immediately, so if the call sigprocmask
unblocks several current pending signals, sigprocmask
at least one of the signals will be delivered before returning.
Below we use the code demonstration to prove our above theory. The following code means that we first mask 2
the number , then print the old signal mask word, and then we print the signal mask word of the current process, and then print the signal mask of the current process When typing, we press the keyboard Ctrl + Cto see if the process will exit. If it does not exit, it means that the current signal is indeed blocked. After the last 5 seconds, the original signal will be restored. Signal No. 2 should be delivered immediately and the process will exit.
#include <iostream>
#include <signal.h>
#include <unistd.h>
// 打印sigset_t结构
void Printset(sigset_t* set)
{
for (int i = 1; i <= 31;i++)
{
if (sigismember(set, i))
{
std::cout << "1";
}
else
{
std::cout << "0";
}
}
}
int main()
{
// 变量的初始化
int count = 0;
sigset_t set, oset;
sigemptyset(&set);
sigemptyset(&oset);
// 设置当前进程的信号屏蔽字
sigaddset(&set, SIGINT);
sigprocmask(SIG_SETMASK, &set, &oset);
// 打印出老的信号屏蔽字
std::cout << "老的信号屏蔽字是:";
Printset(&oset);
std::cout << std::endl;
while (true)
{
std::cout << "目前信号屏蔽字是:";
Printset(&set);
std::cout << std::endl;
if (count++ == 5)
{
// 恢复原来的信号屏蔽字
std::cout << "恢复原来的信号屏蔽字" << std::endl;
sigprocmask(SIG_SETMASK, &oset, &set);
}
sleep(1);
}
return 0;
}
The running results are shown in the figure: the results meet our expectations!
3. System calls about the pending table
We cannot modify the pending table, we can only view it through system calls.
sigpending
This function is very simple. This function will read the pending signal set of the current process and send it out through the set parameter. If the call is successful, it will return 0, and if it fails, it will return -1.
Let's write an example to continue to verify our above principle: we first shield 2
the number signal, and then print the pending signal set of the current process. At the beginning, because the process did not receive the signal, we should see all zeros, and then Then we send a 2
number signal to the process. Since the number 2 signal is blocked, the pending signal set of the current process should be that the second bit is 1, and the others are all 0.
#include <iostream>
#include <cstdlib>
#include <signal.h>
#include <unistd.h>
// 打印sigset_t结构
void Printset(sigset_t* set)
{
for (int i = 1; i <= 31;i++)
{
if (sigismember(set, i))
{
std::cout << "1";
}
else
{
std::cout << "0";
}
}
}
int main()
{
// 变量的初始化
int count = 0;
sigset_t set, oset, pending;
sigemptyset(&set);
sigemptyset(&oset);
// 设置当前进程的信号屏蔽字
sigaddset(&set, SIGINT);
sigprocmask(SIG_SETMASK, &set, &oset);
while (true)
{
// 打印未决信号集
sigpending(&pending);
std::cout << "目前的未决信号集是:";
Printset(&pending);
std::cout << std::endl;
if (count++ == 5)
{
// 恢复原来的信号屏蔽字
std::cout << "恢复原来的信号屏蔽字" << std::endl;
sigprocmask(SIG_SETMASK, &oset, &set);
}
sleep(1);
}
return 0;
}
3. Conclusion
This chapter is about the preservation of process signals. The concept of signal preservation is too much, and the actual operation is relatively small. Therefore, it is necessary to understand block
pending
handler
the table .
In the next chapter, we will continue to understand the processing of process signals in depth, and continue to improve our understanding of signals. Of course, if there are mistakes or deficiencies in this article, please comment or private message to discuss! See you next time, byebye!