I. Signal Set and related operation functions
A signal set is defined as a data type:
Typedef struct {
Unsigned long sig [_ NSIG_WORDS];
} Sigset_t
A signal set is used to describe the set of signals. Each signal occupies one (64-bit ). All signals supported by Linux can appear in the signal set in whole or in part, mainly used in combination with functions related to signal blocking. The following are related functions defined for Signal Set Operations:
# Include <signal. h>
Int sigemptyset (sigset_t * set );
Int sigfillset (sigset_t * set );
Int sigaddset (sigset_t * set, int signum)
Int sigdelset (sigset_t * set, int signum );
Int sigismember (const sigset_t * set, int signum );
Sigemptyset (sigset_t * set) initializes the signal set specified by the set. All signals in the signal set are cleared, which is equivalent to setting 64 to 0;
After sigfillset (sigset_t * set) calls this function, the signal set points to will contain 64 types of signals supported by linux, which is equivalent to setting 1 for 64;
Sigaddset (sigset_t * set, int signum) adds the signum signal to the signal set pointed to by the set, which is equivalent to the position 1 corresponding to the given signal;
Sigdelset (sigset_t * set, int signum) deletes the signum signal in the signal set pointed to by the set, which is equivalent to setting the position 0 corresponding to the given signal;
Sigismember (const sigset_t * set, int signum) determines whether the signal signum is in the signal set pointed to by the set, which is equivalent to checking whether the bit corresponding to the given signal is 0 or 1.
Example program:
#include <stdio.h><unistd.h><stdlib.h><signal.h><sys/types.h> print_sigset(sigset_t * main(&&&&&& print_sigset(sigset_t *(i = ; i < NSIG; ++(sigismember(
Result:
We can see the corresponding position of the added signal. 1. 2. Signal blocking and pending
Man help description:
Signal mask and pending signals
A signal may be blocked, which means that it will not be delivered until it is later unblocked. Between the time when it is generated and when it is delivered a signal is said to be pending. Each thread in a process has an independent signal mask, which indicates the set of signals that the thread is currently blocking. A thread can manipulate its signal mask using pthread_sigmask(3). In a traditional single-threaded application, sigprocmask(2) can be used to manipulate the signal mask.
The processing action of the executed signal is called the Delivery. The state of the signal from generation to Delivery is called the Pending ). A process can Block a signal. When a blocked signal is generated, it remains in the pending state until the process unblocks the signal. Note that blocking and ignoring are different. As long as the signal is blocked, it will not be delivered. Ignoring is an optional action after delivery. Each process has a signal set to describe which signals will be blocked when delivered to the process. All signals in the signal set will be blocked after being delivered to the process.
The representation of signals in the kernel can be viewed as follows:
Figure-based speech:
Block set (blocking set and blocking set): the signal to be blocked by a process. The position of the signal to be blocked is 1.
Pending set: If a signal is in the congestion set of the process, it is also in the corresponding position 1 of the pending set, indicating that the signal cannot be delivered and will not be processed.
Handler (signal processing function set): indicates the signal processing function corresponding to each signal. When the signal is not in the pending concentration, it will be called.
Function operations related to signal blocking and pending operations are as follows:
# Include <signal. h>
Int sigprocmask (int how, const sigset_t * set, sigset_t * oldset ));
Int sigpending (sigset_t * set ));
Int sigsuspend (const sigset_t * mask ));
The sigprocmask () function can operate the signal set based on the parameter how. There are three main operations:
- SIG_BLOCK adds the set signal to the signal set in the current blocked Signal set of the process, which is equivalent to: mask = mask | set
- SIG_UNBLOCK if the process blocking signal contains the signal set points to the signal set, the blocking of the signal is lifted, equivalent to: mask = mask | ~ Set
- SIG_SETMASK updates the blocked Signal set pointing to the set signal set, which is equivalent to the mask = set
Sigpending (sigset_t * set) obtains all signals that have been delivered to the process but are blocked, and returns results in the signal set pointing.
Sigsuspend (const sigset_t * mask) is used to temporarily replace the signal mask of the process with the mask before receiving a signal, and pause the process until the signal is received.
After sigsuspend is returned, the signal mask before the call is restored. After the signal processing function is complete, the process continues to run. The system always returns-1 and sets errno to EINTR.
Example program:
#include <unistd.h><sys/stat.h><sys/wait.h><sys/types.h><fcntl.h><stdlib.h><stdio.h><errno.h><.h><signal.h> ERR_EXIT(m) \ ( handler( printsigset(sigset_t * (i=; i<NSIG; ++ (sigismember( main( argc, *&& (signal(SIGINT, handler) == (signal(SIGQUIT, handler) ==&bset, NULL); && handler( (sig == (sig ==&&&
Result:
Note: The program first adds the SIGINT signal to the process blocking set (shielding set). The SIGINT signal is not sent at the beginning, so there is no signal in the pending state in the process pending set, when we press ctrl + c consecutively, the SIGINT signal is sent to the process. Because the SIGINT signal is in the congestion concentration of the process, the SIGINT signal cannot be delivered, that is, it is in the pending status, so when I print the pending set, I find that the bit corresponding to the SIGINT is 1. Now we press ctrl + \ to send the SIGQUIT signal, because this signal is not blocked by the process, therefore, the SIGQUIT signal is directly delivered, and the corresponding processing function is executed to remove the process blocking the SIGINT signal. Therefore, the previously sent SIGINT signal is delivered and the corresponding processing function is executed, however, because the SIGINT signal is unreliable and does not support queuing, only one signal is delivered.
#include <signal.h><stdio.h><stdlib.h><error.h><.h><unistd.h> MYSIGNAL SIGRTMIN+5 sig_handler( main( argc, **&&&= & (sig = ; sig < NSIG; sig++ (sigismember(&= (flag == &= & (sig = ; sig < NSIG; sig++ (sigismember(&= (flag ==
Result:
The two operations have different results: When two unreliable signals are sent consecutively for the first time and the blocking is finally removed, there is only one delivery, indicating that unreliable signals do not support queuing.
During the second execution, two consecutive reliable signals are sent. After blocking is removed, all signals are delivered, indicating that reliable signals support queuing.
OK. Write this section.