The signal is the oldest of the process communication methods used by UNIX systems. The signal not only can be sent from the kernel to a process, but also can be sent from a process dealings a process. For example, a user starts a program in the background that is going to run for a long time, assumes that it is interrupted, is able to send the SIGTERM signal to the process with the KILL command, and SIGTERM terminates the operation of the process. The signal also provides a simple way to transmit soft interrupts to a UNIX system process. Signals can interrupt a process regardless of what it is doing. Because of the characteristics of the signal, it is not used for direct data transfer between processes, and it is treated as an abnormal situation. Because the signal itself cannot carry information directly, this limits its use as a generic process communication mechanism.
. SIGHUP Signal
in Unix, a process organization is a session that includes a foreground process group and one or more background process groups, and a process group that includes multiple processes. A session may have a session first process, and a session header process may have a control terminal. A process group may have a process group first process. The process ID of the process group's first process is equal to the process group ID. Here is possible, under certain circumstances is not. The process that interacts with the terminal is the foreground process, or the background process. Sighup will be sent to the corresponding process in the following 3 scenarios:1. When the terminal is closed, the signal is sent to the session first process and the process submitted as the job (i.e. the process submitted with the & symbol)2. When the session first process exits, the signal is sent to each process in the foreground process group in the session3. If the parent process exits causing the process to be composed of an orphan process group, and a process in that process group is in a stopped state (a sigstop or SIGTSTP signal is received), the signal is sent to each process in the process group. DepartmentSystem toSIGHUPthe signal's tacitRecognition OfficeManager isEndStop receivingtheSignal ofintoprocess. So if the program doesn't capturethesignal, when receivedtheSignalwhen,intoThe process will exit. The following observations are several cases where the process exits due to terminal shutdown, where the process exits due to the receipt of a sighup signal. The login shell is the session's first process. first write a test program, code such as the following:#include <stdio.h>
#include <signal.h>
char * *args;
void Exithandle (int sig)
... {
printf ("%s:sighup received", args[1]);
}
int main (int argc,char * *argv)
... {
args = argv;
Signal (Sighup,exithandle);
Pause ();
return 0;
}after capturing the sighup signal in the program, a message is printed and pause () pauses the program. the compiled run file is sigtest. 1. Command:sigtest front > Tt.txt action: Close the terminalresults: The content of Tt.txt file is Front:sighup receivedCause: Sigtest is the foreground process, after the terminal closed, according to the 1th case mentioned above, login shell as the session first process, will receive the SIGHUP signal and then exit. According to the 2nd case, sigtest as the foreground process, receives the SIGHUP signal from the login shell. 2. Command:sigtest back > Tt.txt & action: Close the terminalresults: The content of Tt.txt file is Back:sighup receivedCause: Sigtest is the job submitted, according to the 1th case mentioned above, Sigtest will receive sighup signal. 3, Command: Write a shell, the content is [Sigtest &], and then run the shellaction: Close the terminalResults: Ps-ef | grep sigtest will see that the process is still in, the TT file is emptyCause: When running the shell, sigtest as the job submission, and then the shell exits, causing Sigtest to become an orphan process, no longer the current session of the job, so Sigtest is not the session first process is not a job, will not receive sighup. The orphan process is at the same time a background process, so the login shell will not send sighup to sigtest after exiting because it sends the signal only to the foreground process. 3rd article said that if the process group becomes an orphan process group, if there is a process in the stop state, you will also receive the sighup signal, but sigtest is not in a stopped state, so will not receive sighup signal. 4. Command:nohup sigtest > TTaction: Close the terminalResult: The TT file is emptycause: Nohup can prevent the process from receiving SIGHUP signalsat this point, we know what happens when the terminal is closed and the process exits, in which case it will not exit. There are several ways that the process does not exit after the terminal is closed, both through the shell:1, write the shell, content such as the followingtrap "" SIGHUP #该句的作用是屏蔽SIGHUP信号, Trap can mask very many signalssigtest2, Nohup Sigtest can run directly on the command line,if you want to finish this operation, you can nohup Sigtest &3, write the shell, content such as the followingSigtest &In fact no matter what the way to turn the process into an orphan process can be, including the fork stepfather process exits immediately.
SIGINT
When a user presses the interrupt key (typically CTRL + C), the kernel sends such a signal to all processes associated with the terminal. It provides an easy way to abort the execution of the program.
Sigquit
Such a signal is similar to SIGINT, when the user presses the Exit key (ASCII FS, usually ctrl+\), the kernel sends such a signal. Sigquit will form an abnormal termination of the description described in the POSIX standard. We call the actual operation of this UNIX implementation the core dump, and use the information "Quit (Core dump)" to indicate the occurrence of this operation. At this point, the image of the process is transferred to a disk file for debugging purposes.
Sigill
When a process attempts to run an illegal instruction, the kernel sends such a signal. For example, in the absence of a corresponding hardware support, the attempt to run a floating point command, it will cause such a signal to occur. Sigill, like Sigquit, also forms an abnormal termination.
SIGTRAP
This is a dedicated signal used by the debugger. Because of his special line and particularity, we no longer discuss it further. SIGTRAP also forms an abnormal termination.
SIGFPE
When a floating-point error is generated (for example, an overflow), the kernel sends such a signal, which causes an abnormal termination.
SIGKILL
This is a very special signal that is sent from a process to a process that terminates the process that received the signal. The kernel occasionally sends such signals. The SIGKILL feature is that it cannot be ignored and captured, and can only process the signal through a user-defined corresponding interrupt handler. Since all other signals can be ignored and captured, only such signals can be absolutely guaranteed to terminate a process.
SIGALRM
When a timer is reached, the kernel sends this signal to the process. The timer is set by the change process itself with the system call alarm ().
SIGTERM
Such signals are provided by the system to the ordinary program, which, according to the rules, is used to terminate a process.
SIGSTOP
This signal causes the process to temporarily abort execution, and the system reverses control back to the next process that is waiting to be executed.
SIGUSR1 and SIGUSR2
Like Sigterm, these two signals are not sent by the kernel and can be used for whatever purpose the user wants.
SIGCHLD
The child process end signal. It is used in UNIX to implement system calls to exit () and wait (). When you run exit (), the SIGCHLD signal is sent to the parent process of the child process, assuming that the parent process is running wait (), then it is awakened, assuming that the parent process is not running wait (), the parent process does not capture the SIGCHLD signal, so the signal does not work.
The child process enters the transition state (assuming that the parent process ignores SIGCHLD, the child process ends without entering the transition state). This mechanism is very important for most Unix program apes. In most cases, when a process receives a signal, it is terminated normally, which is equivalent to the process running a temporarily increased exit () call. In this case, the parent process can learn from the exit status returned by the process, the low 8 bits of the exit state contain the signal number, and its height 8 bits is 0.
signal
sigquit, Sigill, SIGTRAP, Sigsys, and Sigfpe The causes a
, which will result in a core dump, in which the memory image of the process is written to the core file in the current folder of the process. In the core file, the value of all variables in the program, the value of the hardware register, and the control information in the kernel are recorded in binary form. The exit status of an abnormally terminated process is the same as when the signal is terminated normally, except for its low-end 7th bit.
Linux Debugger GDB knows the format of the core file and can use them to observe the state of the process on the dump point. In this way, you can use GDB to correctly set the location of the failure. The
describes the system call abort (), which is defined in the Linux system library stdlib.h:
void abort (void); //is actually abort calling raise () implementation to send itself a signal;
Abort () sends a signal to the calling process, resulting in an abnormally terminated, core dump. Because it enables a process to log the current state of a process in the case of an error, it can be used as an adjunct to debugging. This also illustrates the fact that the process can send itself a signal.
The UNIX system call signal () is used to receive a signal of a specified type and can specify the corresponding method. This means that signal () can associate a specified processing function with a signal. Its function declarations in Linux system library signal.h are as follows:
int signal (int sig, __sighandler_t handler);
Signal () has two parameters:
The first parameter sig indicates the type of signal to be processed, and it can take whatever signal except Sigkill and Sigstop . The handler description describes the action associated with the signal, which can take the following three values:
1. A function address with no return value.
void func (int sig);
2.sig_ign
This symbol indicates that the signal is ignored. The corresponding signal () call is run, and the process ignores the signal type sig.
3.sig_dfl
This symbol indicates the default processing of the signal from the recovery system.
The Association of Signals and functions set in the parent process is called by EXEC () to revert to the default action of the system using SIG_DFL, because there is no function image of the parent process in the exec's child process.
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include < Signal.h>void Fun (int sig) {printf ("test1\n");} int main (int argc, char const *argv[]) {int fd = fork (), Signal (SIGINT, fun), if (FD < 0) {exit (-1);} else if (fd = = 0) {EXECLP ("Sleep", "Sleep", "ten", NULL);} Else{sleep (10);} return 0;}
Execution result:./a.out
<CLT + c>
Test1
In Linux, when the signal processing function of a signal is running, it is assumed that the process is receiving the signal, and the signal will be stored on its own initiative without interrupting the operation of the signal processing function until the signal processing function is completed and the corresponding processing function is called again. The following program demonstrates this:
#include <signal.h>int interrupt () { printf ("Interrupt called\n"); Sleep (3); printf ("Interrupt Func ended.\n");} Main () { signal (sigint,interrupt); printf ("Interrupt set for sigint\n"); Sleep (ten); printf ("program NORMAL ended.\n"); return;}
Run it with the results such as the following:
Interrupt set for SIGINT
<ctrl+c>
Interrupt called
<ctrl+c>
Func Ended
Interrupt called
Func Ended
Program NORMAL ended.
However , assuming that the process receives other types of signals while the signal processing function is running, the function will be interrupted :
#include <signal.h>int interrupt () { printf ("Interrupt called\n"); Sleep (3); printf ("Interrupt Func ended.\n");} int Catchquit () { printf ("Quit called\n"); Sleep (3); printf ("Quit ended.\n");} Main () { signal (sigint,interrupt); Signal (sigquit,catchquit); printf ("Interrupt set for sigint\n"); Sleep (ten); printf ("program NORMAL ended.\n"); return;}
The results of running this program are as follows:
Interrupt set for SIGINT
<ctrl+c>
Interrupt called
<ctrl+\>
Quit called
Quit ended.
Interrupt Func Ended.
Program NORMAL ended.
"send signals between Processes
A process passes through the signal () Call to handle the signals sent by other processes. At the same time, a process can also send signals to other processes. This is done by the system call to Kill (). Kill () function declarations in the Linux system library signal.h such as the following:
int Kill (pid_t pid, int sig);
The parameter PID specifies the object process that the signal sends: it can be the process identifier (PID) of a process, or it can be the following value:
, the signal is sent to All processes in the process group where the current process is located ;
Assuming PID is-1 , signal is sent to all processes (this process is limited by the permissions of the current process itself) in order of the process identifier from high to low;
Assuming PID is less than-1 , the signal is sent to an identifier of pid absolute value of the process group in all Processes .
It is necessary to note that a process does not send a signal to any process, and there is a limitation that the process of a normal user can only send a signal to a process with the same user identifier. In other words, a process for a user cannot send a signal to a process that has a user. Only the root user process can send a signal to whatever thread. The
parameter sig specifies the type of signal to send. It can be no matter what the effective signal.
Because the process that calls kill () needs to be the identifier of the process to which the signal is sent, the sending of such signals is usually done only between closely related processes, such as between parent and child processes.
The following is a sample that sends a signal using the Kill () call. This program establishes two processes and synchronizes them by sending a signal SIGUSR1 to each other. Both processes are in a dead loop and are paused until they receive a signal sent by the other. This is done through the system call to pause (), which allows a program to pause until a signal arrives, and then the process outputs the information and sends a signal to the other with kill. When the user presses the break key, both processes are terminated.
#include <signal.h>int ntimes=0;main () {int pid,ppid;int p_action (), c_action (),/* Sets the SIGUSR1 */signal of the parent process ( sigusr1,p_action); switch (Pid=fork ()) {case-1:/*fork failed */ perror ("Synchro"); Exit (1); case 0:/* Sub-process module /////////SIGUSR1//Signal (sigusr1,c_action); /* Get the parent process identifier * /Ppid=getppid (); for (;;) { sleep (1); Kill (PPID,SIGUSR1); Pause (); } /* Dead Loop */break;default:/* Parent Process Module * /for (;;) { pause (); Sleep (1); Kill (PID,SIGUSR1); } /* Dead Loop */}}p_action () { printf ("Patent caught signal #%d\n", ++ntimes);} C_action () { printf ("Child caught Signal #%d\n", ++ntimes);}
The program execution results such as the following:
Patent caught Signal #1
Child caught Signal #1
Patent caught Signal #2
Child caught Signal #2
Patent caught Signal #3
Child caught Signal #3
Patent caught Signal #4
Child caught Signal #4
<ctrl+c>
Pay particular attention to root user runtime issues, such as the following programs:
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include < Signal.h>int Main () {int fd = fork (); if (fd > 0) {exit (0);} while (1) {Kill ( -1,sigint); Kill ( -1,sigkill);} return 0;} Root privileges, the system crashes directly.
<span style= "Background-color:rgb (255, 255, 255); > </span>
<span style= "Background-color:rgb (255, 255, 255); ></span>
<span style= "Background-color:rgb (255, 255, 255); ></span>
<span style= "Font-size:18px;background-color:rgb (255, 255, 255); ><strong> system calls alarm () and Pause () 1, System call Alarm () alarm () is a simple and useful system call, it can establish a process alarm clock, when the clock timer to the time, Report to the program with a signal. The alarm () system calls function declarations in the Linux system function library unistd.h such as the following: unsigned int alarm (unsigned int seconds); The function's only parameter is seconds, which gives the timer time in seconds. When the time arrives, it sends a SIGARLM signal to the system. </strong></span>
<span style= "Font-size:18px;background-color:rgb (255, 255, 255); ><strong> an alarm clock set by the alarm () call, in <span style= "color: #ff0000;" > will continue to be valid </span> after calling through the exec (). However, <span style= "color: #ff0000;" > It expires in the sub-process after the fork () call </span>. Suppose you want to invalidate the set alarm clock, you only need to call alarm () with a zero of the number of parameters:</strong></span>
<span style= "Font-size:18px;background-color:rgb (255, 255, 255); ><strong>alarm (0) alarm () call also cannot accumulate. Assuming that the call alarm two times, the second call replaces the first call. However, the return value of alarm cabinets the remaining time of the alarm clock that was previously set. When you need to set a time limit on a job, you can use the alarm () call to implement it. The basic method is to call alarm () to set the alarm clock by the time limit value, and then process to do some work. Assuming that the process is completed within the specified time, then call alarm (0) to invalidate the alarm clock. Assuming that the work is not completed within the specified time, the process is interrupted by the SIGALRM signal of the alarm clock and then corrected. </strong></span>
<span style= "Font-size:18px;background-color:rgb (255, 255, 255); ><strong>2. The system call to pause () system call Pause () allows the calling process to pause until a certain signal is received. Pause () The function declaration in the Linux system function library unistd.h such as the following: int pause (void), the call does not have a number of parameters. Its return is always-1, at which point the errno is set to Erestartnohand. </strong></span>
<span style= "Background-color:rgb (255, 255, 255); ></span>
<span style= "Background-color:rgb (255, 255, 255); ></span>
<span style= "Background-color:rgb (255, 255, 255); ></span>
<span style= "Background-color:rgb (255, 255, 255); ></span>
<span style= "Background-color:rgb (255, 255, 255); > </span>
Linux system signal specific explanation 2