"Copyright Notice: respect for the original, reproduced please retain the source: blog.csdn.net/shallnet or .../gentleliu, the article is for learning communication only, do not use for commercial purposes" the previous section said using the Kill function to send a signal and use the signal function to install the signal place function, this section we use another way to implement the installation signal processing and sending signals. Early UNIX supported only unreliable signals prior to sigrtmin, and later increased the reliable signal from sigrtmin to Sigrtmax, while also increasing the way signal is sent and installed, usingthe Sigqueue () function can send a signal and use the Sigaction function to add a signal. The general signal function is used to install unreliable signals, and sigaction is used to install reliable signals, but in fact two functions can install reliable and unreliable signals.
Use the Sigqueue function instead of the KILL function to send a signal:
#include <signal.h> int sigqueue (pid_t pid, int sig, Const Union Sigval value);
Parameter PID, SIG and kill function two parameters, respectively, the sending signal target process ID and the signal to be sent, the parameter value is to be sent along with the signal to the target signal data, the type of
Union sigval { int sival_int; void *sival_ptr; };
If the receive signal process uses the Sa_siginfo identity to install thesa_sigactionprocessing function, the value is available in the member Si_value of siginfo_t. Use the function sigaction to install a signal handler function:
#include <signal.h> int sigaction (int signum, const struct sigaction *act, struct sigaction *oldact);
The parameter signum is the same as the first parameter of the signal function, which is the signal that the processing function will be installed;The parameter act is the signal processing that will be installed, which is a struct:
struct Sigaction { void (*sa_handler) (int); void (*sa_sigaction) (int, siginfo_t *, void *); sigset_t Sa_mask; int sa_flags; void (*sa_restorer) (void); };
first, two members are signal processing functions,memberSa_handler A second parameter similar to the signal function, which can be a signal processing function or a SIG_DFL or sig_ign. Sa_sigaction has three parameters, the first processing signal, the second parameter is a structsiginfo_t TypeThe third parameter is not used. The structural body siginfo_t is:
siginfo_t {int Si_signo;/* Signal number */int si_errno;/* An errno value */ int Si_code; /* Signal code */int si_trapno; /* Trap number that causedhardware-generated signal (unused to most architectures) */pid_t si_pid; /* Sending Process ID */uid_t Si_uid; /* Real user ID of sending process */int si_status; /* Exit value or signal */clock_t si_utime; /* User Time consumed */clock_t si_stime; /* System Time consumed */sigval_t si_value; /* Signal value */int si_int; /* POSIX.1B signal */void *si_ptr; /* POSIX.1B signal */int si_overrun; /* Timer overrun count; POSIX.1B timers */int si_timerid; /* Timer ID; POSIX.1B timers */void *si_addr; /* Memory location which caused fault */long si_band; /* Band event (is int in glibc 2.3.2 and EarliER) */int si_fd; /* File Descriptor */short SI_ADDR_LSB; /* Least significant bit of address since Linux 2.6.32) */}sigactionmemberThe sa_mask specifies which signals should be blocked during the execution of the signal handler. By default, the current signal itself is blocked, preventing the signal from being nested, unless you specify the Sa_nodefer or Sa_nomask flag bit. The sa_flags contains a number of flags, including the Sa_nodefer and sa_nomask markers just mentioned. Another important flag bit is sa_siginfo, when the flag bit is set, the parameters that accompany the signal can be passed to the signal processing function, so you should specify the handler function for the sa_sigaction in the sigaction structure, and not for the Sa_ handler specifies the signal handler function, otherwise, setting the flag becomes meaningless. Even if the signal processing function is specified for the sa_sigaction, if the sa_siginfo is not set, the signal processing function also cannot get the data transmitted by the signal, and the access to the information in the signal processing function will result in a segment error (segmentation fault). Sa_restorer is no longer used.
When a reliable signal comes to the process, the process adds the signal to the current process's unhandled signal queue, regardless of whether the signal is already contained in the unhandled signal queue, and when an unreliable signal arrives, the process first determines whether the signal queue that is not processed in the current process is already contained and, if it is included, , then the new signal will be lost. Modify the previous section of the sample code to use the Sigaction implementation:
void Sig_func (int signo, siginfo_t *info, void *arg) {//sleep (6); printf ("====%s== [child] handle Signo:%d==arg:%d=\n", __func__, Signo, info->si_int);} void Child_process_do (void) {struct Sigaction act; printf ("====%s==child pid:%d===\n", __func__, Getpid ()); Signal (sigrtmin, sig_func); Signal (SIGALRM, sig_func); Act.sa_sigaction = Sig_func; Act.sa_flags = Sa_siginfo; if (Sigaction (SIGALRM, &act, NULL) < 0) {//Install the signal handler function fprintf (stderr, "sigaction:%s\n", Strerror (errno)). Return } while (1) {sleep (10); }}void Parent_process_do (pid_t pid) {int I, val = 100; Union Sigval Sigarg; Sleep (1); printf ("====%s==parent pid:%d===\n", __func__, Getpid ()); for (i = 0; i < 5; i++) {printf ("====%s==[parent] send signal <%d> to PID <%d>==\n", __func__, SIGR TMIN, PID); Kill (PID, sigrtmin); Kill (PID, SIGALRM); Sigarg.sival_int = val + i; Sigqueue (PID, SIGALRM, SIGARG); The SIGALRM signal is sent here, and the Sigarg is the parameter to be transmitted sleep (1); } waitpid (PID, NULL, 0);} int main (int argc, const char *argv[]) {pid_t pid; PID = fork (); if (PID < 0) {fprintf (stderr, "fork:%s\n", Strerror (errno)); return-1; } if (0 = = pid) {CHILD_PROCESS_DO (); } else {PARENT_PROCESS_DO (PID); } return 0;}No reliable signal can be changed for unreliable signals, no matter how the signal processing is installed. The use of signals to communicate between processes, need to know the other side of the process of the PID, and signal communication can be transmitted in a way that is not a lot of information, in the actual application of the signal may be more used in the process to signal itself, for the process of communication is not much, So using the signal to achieve the IPC is not as convenient as the communication method mentioned in the previous sections. Download the source code in this section:Click to open link
The Linux IPC (eight): signal (bottom)