Signal (up)

Source: Internet
Author: User
Tags posix sigint signal

The linux signal mechanism is far more complex than imagined. This article strives to use the shortest length to make in-depth and meticulous analysis on the machine. You can read the signal application instance (in the signal (below) first, so that you can have a general impression on the process of sending the signal until the corresponding processing function is executed. This article provides application examples of newer functions as much as possible, highlighting these functions.

I. Signal and Signal Source

Signal nature

A signal is a simulation of the interrupt mechanism at the software level. In principle, a process receives a signal and the processor receives an interrupt request. The signal is asynchronous. A process does not have to wait for the signal to arrive through any operation. In fact, the process does not know when the signal will arrive.

Signals are the only asynchronous communication mechanism in the inter-process communication mechanism. They can be seen as asynchronous notifications to notify the processes that receive signals of what happened. After POSIX real-time expansion, the signal mechanism is more powerful. In addition to the basic notification function, it can also transmit additional information.

Signal Source

There are two sources for the occurrence of signal events: hardware sources (for example, we press the keyboard or other hardware faults); software sources, the most common system function for sending signals is kill, raise, alarm, setimer, and sigqueue functions. The software source also includes some illegal operations.

Ii. Signal types

Signals can be classified from two different classification perspectives: (1) Reliability: reliable and unreliable signals; (2) Relationship with time: Real-time and non-real-time signals. All signals supported by the system are listed in Appendix 1 of "inter-process communication in Linux environment (I): pipelines and famous pipelines.

1. Reliable and unreliable Signals

"Unreliable signal"

The Linux signal mechanism is basically inherited from the UNIX system. In early Unix systems, the signal mechanism was relatively simple and original, and some problems were exposed in practice. Therefore, the signals built on the early mechanism were called "unreliable signals ", signals smaller than sigrtmin (in Red Hat 7.2, sigrtmin = 32, sigrtmax = 63) are unreliable signals. This is the source of "unreliable signal. Its main problems are:

  • Each time a process processes a signal, it sets the response to the signal as the default action. In some cases, it may lead to incorrect signal processing. Therefore, if you do not want such an operation, you need to call signal () again at the end of the signal processing function (), reinstall the signal.
  • The signal may be lost, which will be detailed later.
    Therefore, the unreliable signal in early unix mainly refers to the possibility that the process may make a wrong response to the signal and the possible loss of the signal.

Linux supports unreliable signals, but makes improvements to unreliable signal machines: after the signal processing function is called, you do not have to call the signal installation function again (the signal installation function is implemented in a reliable mechanism ). Therefore, the unreliable signals in Linux mainly refer to the possible loss of signals.

"Reliable signal"

With the development of time, practice has proved that it is necessary to improve and expand the original signal mechanism. Therefore, various later Unix versions were studied in this respect to achieve "reliable signals ". Because the originally defined signals have been used in many applications and cannot be modified, we have to add some new signals and define them as reliable signals at the beginning. These signals support queuing, no loss. At the same time, a new version of signal sending and installation has also emerged: the signal sending function sigqueue () and the signal installation function sigaction (). POSIX.4 standardizes reliable signal machines. However, POSIX only standardizes the functions of the reliable signal mechanism and the external interfaces of the signal mechanism, but does not specify the implementation of the signal mechanism.

The signal value between SIGRTMIN and SIGRTMAX is a reliable signal, which overcomes the possibility of signal loss. Linux supports the new version of the signal INSTALLATION function sigation () and the signal sending function sigqueue (). It also supports the early signal () signal INSTALLATION function and the signal sending function kill ().

Note: Do not misunderstand that signals sent by sigqueue () and installed by sigaction are reliable. In fact, a reliable signal is a new signal added later (the signal value is located between SIGRTMIN and SIGRTMAX). An Unreliable signal is a signal whose signal value is smaller than SIGRTMIN. The signal reliability is only related to the signal value, and is not related to the signal sending and installation functions. Currently, signal () in linux is implemented through the sigation () function. Therefore, even if the signal installed by signal () is, at the end of the signal processing function, you do not have to call the signal installation function again. At the same time, real-time signals installed by signal () Support queuing and will not be lost.

For the current two linux signal INSTALLATION functions: signal () and sigaction (), neither of them can convert the signal earlier than SIGRTMIN into a reliable signal (neither supports queuing, but may still be lost, it is still an unreliable signal) and supports queuing for signals after SIGRTMIN. The biggest difference between the two functions is that signals installed by sigaction can transmit information to the signal processing function (which is true for all signals ), however, signals installed by signal cannot transmit information to signal processing functions. The same is true for the signal sending function.

2. Real-time and non-real-time signals

In earlier Unix systems, only 32 types of signals are defined. Ret hat7.2 supports 64 types of signals, numbered 0-63 (sigrtmin = 31, sigrtmax = 63), which may be further increased in the future, this requires Kernel support. The first 32 signals have predefined values. Each signal has a definite purpose and meaning, and each signal has its own default action. If you press Ctrl ^ C on the keyboard, the SIGINT signal is generated. The default reaction to the signal is that the process is terminated. The last 32 signals represent real-time signals, which are equivalent to the reliable signals described above. This ensures that multiple real-time signals are received. Real-time signals are part of the POSIX standard and can be used in application processes.

Non-real-time signals do not support queuing and are all unreliable signals. Real-time signals support queuing and are all reliable signals.

3. Process response to signals

A process can respond to a signal in three ways: (1) Ignore the signal, that is, no processing is performed on the signal. Two signals cannot be ignored: sigkill and sigstop; (2) capture the signal. Define a signal processing function. When a signal occurs, execute the corresponding processing function. (3) perform the default operation. Linux specifies the default operation for each signal, for details, refer to [2] and other materials. Note that the default reaction of a process to a real-time signal is that the process is terminated.

In Linux, which of the above three methods is used to respond to signals depends on the parameters passed to the corresponding API functions.

Iv. Signal Transmission

Main functions for sending signals include: Kill (), raise (), sigqueue (), alarm (), setitimer (), and abort ().

1. Kill ()
# Include <sys/types. h>
# Include <signal. h>
Int kill (pid_t PID, int signo)

Pid Value Signal receiving process
Pid> 0 Pid Process
Pid = 0 Processes in the same process group
Pid <0 pid! =-1 All processes whose process group ID is-pid
Pid =-1 All processes whose IDs are greater than 1 except the sender process itself

Sinno is a signal value. When it is 0 (that is, an empty signal), no signal is actually sent, but an error check is performed as usual. Therefore, it can be used to check whether the target process exists, and whether the current process has the permission to send signals to the target (the root process can send signals to any process, processes with non-root permissions can only send signals to processes belonging to the same session or user ).

Kill () is most commonly used for signal sending when the pid is greater than 0. If the call is successful, 0 is returned. Otherwise,-1 is returned. Note: When the pid is less than 0, it is very simple to describe which processes will receive signals in different versions. Refer to kernel source code kernal/signal. c. The rules in the table above are described in red hat 7.2.

2. raise ()
# Include <signal. h>
Int raise (int signo)
Sends a signal to the process itself. The parameter is the value of the signal to be sent. 0 is returned if the call is successful. Otherwise,-1 is returned.

3. sigqueue ()
# Include <sys/types. h>
# Include <signal. h>
Int sigqueue (pid_t pid, int sig, const union sigval val)
0 is returned if the call is successful. Otherwise,-1 is returned.

Sigqueue () is a relatively new system call for sending signals, mainly for real-time signals (of course, the first 32 types are also supported). It supports signal parameters and functions sigaction () in combination.

The first parameter of sigqueue is the process ID of the received signal, the second parameter is used to determine the signal to be sent, and the third parameter is a combined data structure union sigval, which specifies the signal transmission parameter, 4-byte value.

 typedef union sigval { int  sival_int; void *sival_ptr; }sigval_t;

Sigqueue () transmits more additional information than kill (), but sigqueue () can only send signals to one process, rather than to one process group. If signo is set to 0, an error check is executed, but no signal is actually sent. A 0 signal can be used to check the validity of the PID and whether the current process has the permission to send signals to the target process.

When sigqueue is called, the information specified by sigval_t will be copied to the 3-parameter signal processing function (3-parameter signal processing function indicates that the signal processing function is installed by sigaction and the sa_sigaction pointer is set, in the siginfo_t structure, the signal processing function can process the information. Because sigqueue system calls support sending parameters, it is more flexible and powerful than kill () system calls.

Note: When sigqueue () sends a non-real-time signal, the information contained in the third parameter can still be transmitted to the signal processing function. When sigqueue () sends a non-real-time signal, queuing is still not supported, that is, all the same signals that come when the signal processing function is executed are merged into one signal.

4. Alarm ()
# Include <unistd. h>
Unsigned int alarm (unsigned int seconds)
Specifically set for the sigalrm signal. After the specified time is seconds, the sigalrm signal will be sent to the process itself, also known as the alarm time. After a process calls alarm, any previous alarm () call will be invalid. If the seconds parameter is zero, no alert time is included in the process.
Return value. If the alarm time has been set in the process before calling alarm (), the remaining time of the previous alarm time is returned; otherwise, 0 is returned.

5. setitimer ()
# Include <sys/time. h>
Int setitimer (INT which, const struct itimerval * value, struct itimerval * ovalue ));
Setitimer () is more powerful than alarm and supports three types of Timers:

  • ITIMER_REAL: sets the absolute time. After the specified time, the kernel sends the SIGALRM signal to the current process;
  • ITIMER_VIRTUAL sets the program execution time. After the specified time, the kernel sends the SIGVTALRM signal to the process;
  • ITIMER_PROF sets the time consumed by the process execution and the kernel because of the current process. After the specified time, the kernel sends the ITIMER_VIRTUAL signal to the current process;

Setitimer () the first parameter which specifies the timer type (one of the above three); the second parameter is an instance of the structure itimerval. For the structure of itimerval, see Appendix 1. The third parameter cannot be processed.

If setitimer () is called successfully, 0 is returned; otherwise,-1 is returned.

6. Abort ()
# Include <stdlib. h>
Void abort (void );

Send a sigabort signal to a process. By default, the process exits abnormally. Of course, you can define your own signal processing function. Even if sigabort is set as a blocking signal by the process, after calling abort (), sigabort can still be received by the process. This function has no return value.

5. Signal installation (set signal Association)

If a process needs to process a signal, it must be installed in the process. The installation signal is mainly used to determine the ing between the signal value and the action of the process against the signal value, that is, the signal to be processed by the process, and the operation to be performed when the signal is transmitted to the process.

Linux mainly has two function implementation signals: Signal () and sigaction (). Signal () is implemented based on reliable signal system calls and is a database function. It has only two parameters and does not support signal transmission information. It is mainly used for the installation of the first 32 non-real-time signals, while sigaction () is a newer function (called by two systems: sys_signal and sys_rt_sigaction) have three parameters that support signal transmission information and are mainly used in combination with sigqueue () system calls. Of course, sigaction () also supports non-real-time signal installation. Sigaction () is superior to signal () mainly because it supports signal parameters.

1. Signal ()
# Include <signal. h>
Void (* signal (int signum, void (* Handler) (INT );
If the function prototype is not easy to understand, you can refer to the decomposition method below to understand:
Typedef void (* sighandler_t) (int );
Sighandler_t signal (int signum, sighandler_t handler ));
The first parameter specifies the signal value, and the second parameter specifies the processing of the previous signal value, which can be ignored (the parameter is set to SIG_IGN ); you can use the default signal processing method (the parameter is set to SIG_DFL), or you can implement the processing method by yourself (the parameter specifies a function address ).
IF signal () is called successfully, return the handler value when signal () is called for the last signum installation signal; If signal () fails, return SIG_ERR.

2. sigaction ()
# Include <signal. h>
Int sigaction (int signum, const struct sigaction * act, struct sigaction * oldact ));

The sigaction function is used to change the behavior of a process after receiving a specific signal. The first parameter of this function is the signal value, which can be any specific valid signal Except SIGKILL and SIGSTOP (define your own processing function for these two signals, will cause a signal installation error ). The second parameter is a pointer to an instance of the sigaction structure. In the instance of the sigaction structure, the processing of specific signals is specified, which can be blank, the process processes the signal by default. The third parameter oldact points to the object to save the original processing of the corresponding signal. You can specify oldact as NULL. If the second and third parameters are set to NULL, this function can be used to check the signal validity.

The second parameter is the most important, including the processing of the specified signal, the information transmitted by the signal, and the functions to be shielded during the execution of the signal processing function.

The sigaction structure is defined as follows:

struct sigaction {union{__sighandler_t _sa_handler;void (*_sa_sigaction)(int,struct siginfo *, void *);
     }_u                   sigset_t sa_mask;                  unsigned long sa_flags;               void (*sa_restorer)(void);              }

Sa_restorer is out of date and POSIX does not support it and should not be used again.

1. The two elements _ sa_handler and * _ sa_sigaction in the combined data structure specify the signal Association function, that is, the user-specified signal processing function. In addition to user-defined processing functions, it can also be SIG_DFL (using the default processing method) or SIG_IGN (ignoring signals ).

2. The processing function specified by _ sa_handler has only one parameter, namely, the signal value. Therefore, the signal cannot transmit any information except the signal value; the signal processing function specified by _ sa_sigaction has three parameters and is set for real-time signals (of course, non-real-time signals are also supported). It specifies a three-parameter signal processing function. The first parameter is the signal value, the third parameter is not used (posix has no standard to use this parameter), and the second parameter is a pointer to the siginfo_t structure, the structure contains the data value carried by the signal. The structure pointed to by the parameter is as follows:

Siginfo_t {int si_signo;/* signal value, meaning for all signals */int si_errno;/* errno value, meaning for all signals */int si_code;/* signal generation reason, make sense for all signals */union {/* federated data structure, and different members adapt to different signals */
     // Ensure that a sufficient storage space is allocated for int _ pad [SI_PAD_SIZE]; // structure struct {...} ...... meaningful to SIGKILL {...}............... // structure that makes sense to SIGILL, SIGFPE, SIGSEGV, and SIGBUS: struct {...}.........}}

Note: For easier reading, this structure is often expressed in Appendix 2 when explaining the problem.

The Union data member in the siginfo_t structure ensures that the structure adapts to all signals. For real-time signals, the following structure is used:

typedef struct {int si_signo;int si_errno;int si_code;union sigval si_value;} siginfo_t;

The fourth domain of the structure is also a joint data structure:

union sigval {int sival_int;void *sival_ptr;}

The combined data structure indicates that the si_value in the siginfo_t structure either holds a 4-byte integer or a pointer, which constitutes the signal-related data. The signal processing function contains such signal-related data pointers, but does not specify how to operate the data. The procedure should be agreed by the program developers according to the specific task.

When the system calls sigqueue to send signals, the third parameter of sigqueue is the combined sigval data structure. When sigqueue is called, the data in the data structure will be copied to the second parameter of the signal processing function. In this way, the signal can be sent with additional information. It is very meaningful for Program Development to transmit signals.

The signal parameter transmission process is shown as follows:

3. sa_mask specifies which signals should be blocked during the execution of the signal processing program. By default, the current signal is blocked to prevent nested transmission of the signal, unless the SA_NODEFER or SA_NOMASK flag is specified.

Note: The prerequisite for signal blocking specified by sa_mask is that the signal specified by sa_mask is blocked only when the processing function of the signal is executed by sigaction.

4. sa_flags contains many flag spaces, including the SA_NODEFER and SA_NOMASK. Another important flag is SA_SIGINFO. When this flag is set, the parameters attached to the signal can be passed to the signal processing function. Therefore, you should specify a processing function for sa_sigaction in the sigaction structure instead of a signal processing function for sa_handler. Otherwise, setting this flag becomes meaningless. Even if a signal processing function is specified for sa_sigaction, if SA_SIGINFO is not set, the signal processing function cannot obtain the data transmitted from the signal, access to this information in the signal processing function will lead to a segment error (Segmentation fault ).

Note: many documents have stated that if this flag is set, three-parameter signal processing functions must be defined. This is not the case. The verification method is simple: implement a single parameter signal processing function and set this flag in the program to view the running result of the program. In fact, you can regard this flag as a switch for whether to transmit a parameter. If this bit is set, a parameter is transmitted. Otherwise, no parameter is transmitted.

Vi. Signal Set and Signal Set operation functions:

A signal set is defined as a data type:

typedef struct {unsigned long sig[_NSIG_WORDS];} sigset_t

The signal set is used to describe the signal set. 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, and all signals in the signal set are cleared; sigfillset (sigset_t * set) after this function is called, the signal set points to will contain 64 types of signals supported by linux; sigaddset (sigset_t * set, int signum) will add signum signals to the signal set points; sigdelset (sigset_t * Set, int signum) Delete the signum signal in the signal set to which the set points; sigismember (const sigset_t * set, int signum) Determine whether the signal signum is in the signal set to which the set points.

VII. Signal blocking and pending signal:

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 following are functions related to signal blocking:

#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:

Parameter how Current process Signal Set
SIG_BLOCK Add the set signal to the signal set in the current blocked Signal set of the process
SIG_UNBLOCK If the process blocking signal contains a signal from the set point to the signal set, the blocking of the signal is lifted.
SIG_SETMASK Update the signal set to which the process blocking signal set points

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.

Appendix 1: Structure itimerval:

            struct itimerval {                struct timeval it_interval; /* next value */                struct timeval it_value;    /* current value */            };            struct timeval {                long tv_sec;                /* seconds */                long tv_usec;               /* microseconds */            };

Appendix 2: Descriptive description of the second parameter in the three-parameter signal processing function:

Siginfo_t {int si_signo;/* signal value, meaning for all signals */INT si_errno;/* errno value, meaning for all signals */INT si_code;/* signal generation reason, make sense to all signals */pid_t si_pid;/* process ID of the signal sending, make sense to the kill (2), real-time signal and sigchld */uid_t si_uid; /* real User ID of the sending signal process, which is meaningful to kill (2), real-time signal, and sigchld */INT si_status;/* exit status, which is meaningful to sigchld */clock_t si_utime; /* Time consumed by the user, meaningful to sigchld */clock_t si_stime;/* Time consumed by the kernel, meaningful to sigchld */sigval_t si_value;/* signal value, meaningful to all real-time, it is a joint data structure and can be an integer (indicated by si_int or a pointer indicated by si_ptr) */void * si_addr;/* memory address that triggers fault, it makes sense for sigill, sigfpe, SIGSEGV, and sigbus signals */INT si_band;/* it makes sense for sigpoll signals */INT si_fd;/* it makes sense for sigpoll signals */}

In fact, apart from the first three elements, other elements are organized in a consortium structure. In the consortium data structure, they are organized into different structures based on different signals. The meaning of a signal mentioned in the comment refers to the ability to access these domains in the signal processing function to obtain meaningful information related to the signal, however, a specific signal is only interested in specific information.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.