Table of Contents
- 1. Signal set
- 2. Custom signal set related functions
- 3. sigprocmask function
-
-
- function analysis
- code example
-
Orange
1. Signal set
-
A collection of multiple signals is called a signal set, and its system data type is sigset_t.
-
There are two very important signal sets in the PCB, one is called “blocked signal set” and the other is “pending signal set”. Signals are generated but not processed (pending), and all unprocessed signals are stored in a set (pending signal set) in the kernel. The signal in this pending state needs to be processed. Before processing, it needs to be compared with another signal set (blocking signal set). When processing, it is queried with the flag bit in the blocking signal set to see if the signal is blocked. up.
-
The “pending” of a signal is a state, which refers to the period from the generation of the signal to the time before the signal is processed.
-
The “blocking” of a signal is a switch action, which means preventing the signal from being processed, but not preventing the signal from being generated.
-
Signal blocking is to let the system temporarily reserve the signal for later transmission. Since there are other ways to make the system ignore the signal, the blocking of the signal is generally only temporary, just to prevent the signal from interrupting the sensitive operation.
2. Custom signal set related functions
The following signal set-related functions operate on custom signal sets
/* int sigemptyset(sigset_t *set); - Function: Clear the data in the signal set, and set all the flag positions in the signal set to 0 - Parameters: set, outgoing parameters, signal set to be operated - Return value: success returns 0, failure returns -1 int sigfillset(sigset_t *set); - Function: Set all flags in the signal set to 1 - Parameters: set, outgoing parameters, signal set to be operated - Return value: success returns 0, failure returns -1 int sigaddset(sigset_t *set, int signum); - Function: Set the flag bit corresponding to a signal in the signal set to 1, indicating that the signal is blocked - parameters: - set: Outgoing parameters, the set of signals that need to be operated - signum: The signal that needs to be blocked - Return value: success returns 0, failure returns -1 int sigdelset(sigset_t *set, int signum); - Function: Set the flag bit corresponding to a signal in the signal set to 0, indicating that the signal will not be blocked - parameters: - set: Outgoing parameters, the set of signals that need to be operated - signum: Need to set the signal that does not block - Return value: success returns 0, failure returns -1 int sigismember(const sigset_t *set, int signum); - Function: determine whether a signal is blocked - parameters: - set: the set of signals that need to be operated - signum: the signal that needs to be judged - return value: 1: signum is blocked 0 : signum does not block -1 : failed */
Code Example
#include <signal.h> #include <stdio.h> int main() {<!-- --> // Create a signal set, some flags may be 1 at the beginning, so the next step needs to be cleared sigset_t set; // Clear the content of the signal set sigemptyset( & amp;set); // Determine whether SIGINT is in the signal set set int ret = sigismember( & amp; set, SIGINT); if(ret == 0) {<!-- --> printf("SIGINT does not block\ "); } else if(ret == 1) {<!-- --> printf("SIGINT blocked\ "); } // Add several signals to the signal set sigaddset( & set, SIGINT); sigaddset( &set, SIGQUIT); // Determine whether SIGINT is in the signal set ret = sigismember( & amp; set, SIGINT); if(ret == 0) {<!-- --> printf("SIGINT does not block\ "); } else if(ret == 1) {<!-- --> printf("SIGINT blocked\ "); } // Determine whether SIGQUIT is in the signal set ret = sigismember( & amp; set, SIGQUIT); if(ret == 0) {<!-- --> printf("SIGQUIT does not block\ "); } else if(ret == 1) {<!-- --> printf("SIGQUIT blocked\ "); } // remove a signal from the signal set sigdelset( &set, SIGQUIT); // Determine whether SIGQUIT is in the signal set ret = sigismember( & amp; set, SIGQUIT); if(ret == 0) {<!-- --> printf("SIGQUIT does not block\ "); } else if(ret == 1) {<!-- --> printf("SIGQUIT blocked\ "); } return 0; }
3, sigprocmask function
Function Analysis
/* int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); - Function: Set the data in the custom signal set to the kernel (set blocking, unblocking, replacement) - parameters: - how : How to handle the kernel blocking signal set SIG_BLOCK: Add the blocking signal set set by the user to the kernel, and the original data in the kernel remains unchanged Assuming the default blocking signal set in the kernel is mask, mask | set SIG_UNBLOCK: According to the data set by the user, unblock the data in the kernel mask & amp;= ~set (that is, first negate set, and then bitwise AND with mask), assuming that the default blocking signal set in the kernel is mask SIG_SETMASK: Overwrite the original value in the kernel - set : User-defined signal set that has been initialized - oldset : saves the state of the blocking signal set in the kernel before setting, can be NULL - return value: Success: 0 Failed: -1 Set error numbers: EFAULT, EINVAL int sigpending(sigset_t *set); - Function: Get the pending signal set in the kernel - Parameters: set, the outgoing parameter, saves the information in the pending signal set in the kernel. */
Code Example
The code first defines the signal set set and puts the SIGINT and SIGQUIT signals into it. Then the set of blocking signals in the kernel is modified through the sigprocmask function. Then an infinite loop is set, a signal set pendingset is created in the loop, and the data of the current pending signal set is put into the pendingset, and then the first 31 bits of the signal set are traversed.
When you run the program, the first output will be 0, and then press ctrl + c before looping 10 times, and the second digit printed will change from 0 to 1 (in fact, when you press ctrl + c , which means sending a SIGINT signal to the system, but the signal has been set to 1 in the blocking signal set in the kernel through the above operation, so when the system receives the signal, it will also block, so the signal status is unavailable decision, the second bit (representing SIGINT) of the printed pending signal set becomes 1).
After 10 cycles, the blockage is unblocked. Before pressing ctrl + c, there is no way to stop the infinite loop, but after pressing ctrl + c and looping 10 times, the infinite loop will automatically stop, because after the program is set 10 times, the signal blocking we set before is released, and the system is no longer The previously sent SIGINT signal is blocked, so the SIGINT signal does its thing and stops the process.
// Write a program to print the pending status of all regular signals (1-31) to the screen // Set some signals to be blocked, and generate these signals through the keyboard #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> int main() {<!-- --> // Set signal No. 2 and No. 3 to block sigset_t set; sigemptyset( & amp;set); // Add signals No. 2 and No. 3 to the signal set sigaddset( & set, SIGINT); sigaddset( &set, SIGQUIT); // Modify the set of blocking signals in the kernel sigprocmask(SIG_BLOCK, & set, NULL); int num = 0; while(1) {<!-- --> num++; // Get the data of the current pending signal set sigset_t pendingset; sigemptyset( &pendingset); sigpending( &pendingset); // traverse the first 32 bits for(int i = 1; i <= 31; i ++ ) {<!-- --> if(sigismember( & amp;pendingset, i) == 1) {<!-- --> printf("1"); }else if(sigismember( & amp;pendingset, i) == 0) {<!-- --> printf("0"); } else {<!-- --> perror("sigismember"); exit(0); } } printf("\ "); sleep(1); if(num == 10) {<!-- --> // unblock sigprocmask(SIG_UNBLOCK, & set, NULL); } } return 0; }