Linux inter-process communication-Use signals

Source: Internet
Author: User
I. What are the signals that have been used in Windows? We all know that when we cannot end a program normally, we can use the task manager to force the process to end. But how is this actually implemented? In Linux, the same function is implemented by generating and capturing signals. A running process captures this signal and then performs some operations and is terminated. A signal is an event generated when the Unix and Linux systems respond to certain conditions. The process that receives the signal will take some action accordingly. Generally, a signal is generated by an error. But they can also be used as a way of inter-process communication or modifying behavior, explicitly sent by one process to another. The generation of a signal is called generation, and the receipt of a signal is called capture. 2. Signal type the signal name is in the header file signal. as defined in H, signals start with sig, and there are not many commonly used signals. The commonly used signals are as follows: For more signal types, see the appendix. 3. Signal Processing-the signal function program can use the signal function to process a specified signal, mainly by ignoring and restoring its default behavior. The prototype of the signal function is as follows:
#include <signal.h>void (*signal(int sig, void (*func)(int)))(int);
This is a very complex statement. Be patient and you can know that signal is a function with SIG and func parameters. func is a function pointer of the void (*) (INT) type. This function returns a pointer of the same type as func, pointing to the function pointer of the previously specified signal processing function. Parameters of the signal to be captured are provided by Sig. The function to be called after the specified signal is received is provided by the func parameter. In fact, the use of this function is quite simple, you can see through the example below. Note that the prototype of the signal processing function must be void.
Func (INT), or the following special value: sig_ign: Ignore the signal sig_dfl: the default behavior of the recovery signal is said so much. Let's give an example to illustrate it. The source file is signal1.c, the Code is as follows:
# Include <signal. h> # include <stdio. h> # include <unistd. h> void ouch (INT sig) {printf ("\ nouch! -I got signal % d \ n ", sig); // restores the default behavior of the terminal interrupt signal SIGINT (void) signal (SIGINT, sig_dfl);} int main () {// change the default behavior of the terminal interrupt signal SIGINT to execute the ouch function // instead of terminating the program execution (void) signal (SIGINT, ouch); While (1) {printf ("Hello world! \ N "); sleep (1);} return 0 ;}
The running result is as follows:
As you can see, the process is not terminated when you press the terminate command (CTRL + C) for the first time, and the output is ouch! -I got signal 2, because the default SIGINT behavior is changed by the signal function, when the process receives the signal SIGINT, it calls the ouch function for processing, note that the ouch function changes the processing method of the signal SIGINT to the default method. Therefore, when you press Ctrl + C again, the process is terminated as before. 4. Signal Processing-The sigaction function we see in front of the signal function for signal processing, but generally we can use a more robust signal interface-The sigaction function. Its prototype is:
#include <signal.h>int sigaction(int sig, const struct sigaction *act, struct sigaction *oact);
Similar to the signal function, this function is used to set the action associated with the signal Sig. If oact is not a null pointer, it is used to save the original position of the action on the signal, act is used to set the action of the specified signal. The sigaction struct is defined in signal. h, but it includes at least the following members: void (*) (INT) sa_handler; handler function pointer, which is equivalent to the func parameter of the signal function. Sigset_t sa_mask; Specify one. Signal Set. before calling the signal processing function pointed to by sa_handler, the signal set will be added to the signal shielding word of the process. Signal shielding refers to a set of signals currently blocked. They cannot be received by the current process to int sa_flags; Signal Processing modifier; the value of sa_mask is usually set by using the signal set function, the signal set function will be detailed in my next article-Linux inter-process communication-Signal Set function. Sa_flags can usually take the following values: in addition, we use the signal or sigaction function to specify a function to process signals, but if the signal processing function receives the signal to be processed before it is established, what will happen to the process? It will not be processed using our set processing functions as we imagined. Sa_mask can solve this problem. sa_mask specifies a signal set. before calling the signal processing function pointed to by sa_handler, the signal set will be added to the signal shielding word of the process, set the signal shielding character to prevent the signal from being received when its processing function is not completed, that is, the sa_mask field can be used to eliminate this race condition. Take the above example. The following example code is rewritten using the sigaction function. The source file is signal2.c. The Code is as follows:
# Include <unistd. h> # include <stdio. h> # include <signal. h> void ouch (INT sig) {printf ("\ nouch! -I got signal % d \ n ", sig);} int main () {struct sigaction Act; Act. sa_handler = Ouch; // create an empty signal shielding word, that is, do not shield any information sigemptyset (& act. sa_mask); // reset the sigaction function to the default act. sa_flags = sa_resethand; sigaction (SIGINT, & act, 0); While (1) {printf ("Hello world! \ N "); sleep (1);} return 0 ;}
The running result is the same as that in the previous example. Note that the sigaction function is not reset by default. If you want to reset it, sa_flags must be sa_resethand. 5. the functions mentioned above indicate how some processes respond to a signal after receiving a signal, that is, the signal processing problem, is there any function that can actively send a signal to a process? We can send a signal through two functions: Kill and alarm. 1. Let's take a look at the kill function. A process can send a signal to other processes including itself through the kill function. If the program has no permission to send this signal, the call to the kill function fails, and the common cause of failure is that the target process is owned by another user. It's easy to think about it. You can't control other people's programs. Of course, Super User Root, this kind of God exists. The prototype of the kill function is:
#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);
It sends the signal sig to the process whose process number is PID, and returns 0 if the process is successful. -1 is returned if the kill call fails. The call fails for three reasons: 1. the given signal is invalid (errno = einval). 2. The sending permission is insufficient (errno = eperm) 3. The target process does not exist (errno = esrch). 2. The alarm function has the same name as the function. It provides an alarm function, A process can call the alarm function to send a sigalrm signal after a specified time. The alarm function type is as follows:
#include <unistd.h>unsigned int alarm(unsigned int seconds);
The alarm function is used to send a sigalrm signal after seconds. If seconds is set to 0, all configured alarm alarms are canceled. The Return Value of the alarm function is the remaining seconds of the previously set alarm time. If the return value fails,-1 is returned. The following describes how to use the fork, sleep, and signal functions. The source file is signal3.c and the code is as follows:
# Include <unistd. h> # include <sys/types. h> # include <stdlib. h> # include <stdio. h> # include <signal. h> static int alarm_fired = 0; void ouch (INT sig) {alarm_fired = 1 ;}int main () {pid_t PID; pid = fork (); Switch (PID) {Case-1: perror ("fork failed \ n"); exit (1); case 0: // sub-process sleep (5 ); // send the signal kill (getppid (), sigalrm); exit (0); default: ;}// set the processing function signal (sigalrm, ouch); While (! Alarm_fired) {printf ("Hello world! \ N "); sleep (1);} If (alarm_fired) printf (" \ ni got a signal % d \ n ", sigalrm); exit (0 );}
The running result is as follows:
In the code, we copied a new process using the fork call. In the child process, a sigalrm signal is sent to the parent process five seconds later, and the signal is captured in the parent process, use the ouch function to change the value of alarm_fired and exit the loop. 5 Hello world! Then, the program receives a sigarlm signal and ends the process. Note: If the parent process has nothing to do before the signal of the child process arrives, we can use the pause () function to suspend the parent process until the parent process receives the signal. When a process receives a signal, the preset signal processing function starts to run and the program resumes normal execution. This can save CPU resources, because it can avoid a loop to wait. In this example, we can change the while loop to a pause (). Next we will illustrate the usage of the alarm and pause functions with a small example. The source file is signal4.c, the Code is as follows:
# Include <unistd. h> # include <sys/types. h> # include <stdlib. h> # include <stdio. h> # include <signal. h> static int alarm_fired = 0; void ouch (INT sig) {alarm_fired = 1;} int main () {// signal processing function signal (sigalrm, ouch ); // call the alarm function and send the signal sigalrmalarm (5) after 5 seconds; // suspend the process pause (); // After receiving the signal, restore normal execution if (alarm_fired = 1) printf ("receive a signal % d \ n", sigalrm); exit (0 );}
The running result is as follows: After five seconds, the process receives a sigalrm, resumes running, prints information, and exits. 6. Think about the security of the signal processing function. When a process receives a signal, it is transferred to the function you are associated with for execution. However, during execution, how does a program execute when a process receives the same signal or another signal and executes the related function? That is to say, the signal processing function can be interrupted during its execution and called again. When it is returned to the first call, it is critical that it can continue the correct operation. This is not just a recursive issue, but a reentrant (that is, it can be completely entered and re-executed) problem. In contrast, in Linux, the kernel is responsible for handling interrupt service routines of multiple devices at the same time, higher-priority interruptions may be "inserted" during the execution of the same piece of code. To put it simply, if our signal processing functions can be reentrant, they can be retained and re-executed again after they exit, so that the signal processing functions can be reentrant, you cannot call a function that cannot be reentrant in information processing functions. The following lists the reentrant functions. functions in this table cannot be reentrant. The reentrant function table is as follows: VII. Appendix-Signal Table if the process receives one of the above signals and has not been scheduled to capture it in advance, the process will terminate. There are other signals as follows:

Related Article

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: info-contact@alibabacloud.com 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.