Signal details in linux System 2

Source: Internet
Author: User

SignalIs the oldest process communication method used by UNIX systems. Signals can not only be sent from the kernel to one process, but also from one process to another. For example, if you start a program that needs to run for a long time in the background and want to interrupt its execution, you can use the kill command to send the SIGTERM signal to the process, SIGTERM will terminate the execution of this process. The signal also provides a simple method to transmit soft interruptions to UNIX system processes. A signal can interrupt a process, regardless of what it is doing. Because of the characteristics of the signal, it is not used for direct data transmission between processes, but for processing abnormal conditions. Because the signal itself cannot carry information directly, this restricts it as a general process communication mechanism.

. SIGHUP Signal

In UNIX, the process organization structure is session. It contains one foreground process group and one or more background process groups. A process group contains multiple processes. A session may have a session first process, and a session first process may have a control terminal. A process group may have a first process in the process group. The process ID of the first process in the process group is equal to that of the Process Group. There may be, but under some circumstances, none. The process that interacts with the terminal is the foreground process, otherwise it is the background process. SIGHUP will be sent to the corresponding process in the following three cases: 1. When the terminal is disabled, this signal is sent to the first process of the session and the process submitted as the job (that is, the process submitted with the & symbol). 2. When the first process of the session exits, this signal is sent to every process in the front-end process group of the session. 3. If the parent process exits, the process becomes an orphan process group, if a process in the process group is in the stopped status (receives the SIGSTOP or SIGTSTP signal), the signal is sent to every process in the process group. The system processes the SIGHUP signal by default and terminates the process that receives the signal. Therefore, if the program does not capture the signal, the process will exit when it receives the signal. Next we will observe several cases where the process exits due to terminal shutdown. Here the process exits because it receives the SIGHUP signal. Login shell is the first process of the session. First, write a test program. The Code is as follows: # 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;
} A piece of information is printed after the SIGHUP signal is captured in the program, and pause () stops the program. The compiled execution file is sigtest. 1. Command: sigtest front> tt.txt operation: Close the terminal result: the content of the tt.txt file is front: sighup received ed. Original cause: sigtest is the front-end process. After the terminal is closed, according to the above 1st cases, login shell, as the first process of the session, will receive the SIGHUP signal and then exit. According to the 2nd cases, as the foreground process, sigtest receives the SIGHUP signal from login shell. 2. Command: sigtest back> tt.txt & Operation: Close the terminal. Result: The content of the tt.txt file is back: sighup received ed. The original cause is: sigtest is a submitted job, according to the above 1st cases, sigtest will receive a SIGHUP signal. 3. Life order: Write a shell with the content of [sigtest &], and then execute the shell operation: Close the terminal. Result: ps-ef | grep sigtest: the process is still running. The tt file is empty. The source cause: when the shell is executed, sigtest is submitted as a job, and the shell exits, as a result, sigtest becomes an orphan process and is no longer the job of the current session. Therefore, sigtest is neither the first process of the session nor the job and will not receive SIGHUP. At the same time, the orphan process is a background process. Therefore, after login shell exits, it does not send SIGHUP to sigtest, because it only sends this signal to the foreground process. Article 3 it is said that if a process group becomes an orphan process group, if a process is in the stopped status, it will also receive a SIGHUP signal, but sigtest is not in the stopped status, so it will not receive a SIGHUP signal. 4. Command Line: nohup sigtest> tt operation: Close the terminal. Result: The tt file is empty. The original cause: nohup can prevent the process from receiving the SIGHUP signal, we know under what circumstances the process will exit after the terminal is closed, and under what circumstances it will not exit. The following methods can be used to prevent a process from exiting after the terminal is closed: 1. Write a shell with the following content: trap "" SIGHUP # the function of this sentence is to shield the SIGHUP signal, trap can shield many signals, such as sigtest2 and nohup sigtest, which can be executed directly on the command line. If you want to continue other operations after this operation, you can compile nohup sigtest & 3 and shell, the content is as follows: sigtest & in fact, any way to turn the process into an orphan process can be done, including fork's immediate termination of the parent process. SIGINT
When a user presses the interrupt key (usually Ctrl + C), the kernel sends this signal to all processes associated with the terminal. It provides a simple way to stop running programs.
SIGQUIT
This signal is very similar to SIGINT. When you press the return key (ASCII code FS, usually Ctrl + \), the kernel sends this signal. SIGQUIT will form an abnormal termination described by POSIX standards. We call the actual operation of this UNIX implementation as core dump and use the information "Quit (core dump)" to point out the occurrence of this operation. In this case, the image of the process is stored in a disk file for debugging.
SIGILL
The kernel sends this signal when a process attempts to execute an illegal command. For example, if you attempt to execute a floating point command without the corresponding hardware support, this signal may occur. Similar to SIGQUIT, SIGILL is terminated abnormally.
SIGTRAP
This is a dedicated signal used by the debugging program. Due to its special nature and special nature, we will not discuss it further. SIGTRAP also forms an abnormal termination.
SIGFPE
When a floating point error occurs (such as overflow), the kernel sends this signal, which leads to abnormal termination.
SIGKILL
This is a very special signal, which is sent from one process to another, so that the process receiving the signal stops. The kernel occasionally sends this signal. SIGKILL features that it cannot be ignored or captured and can only process the signal through a user-defined interrupt handler. Because all other signals can be ignored and captured, only such signals can definitely terminate a process.
SIGALRM
When a timer arrives, the kernel sends this signal to the process. The timer is set by the change process using the system to call alarm.
SIGTERM
This signal is provided by the system to common programs and is used to terminate a process as required.
SIGSTOP
This signal causes the process to temporarily stop running, and the system switches the control back to the waiting process.
SIGUSR1 and SIGUSR2
Like SIGTERM, these two signals are not sent by the kernel and can be used for any purpose the user wishes.
SIGCHLD
The sub-process end signal. UNIX uses it to implement system call exit () and wait (). When exit () is executed, the SIGCHLD signal is sent to the parent process of the child process. If the parent process is executing wait (), it is awakened; if the parent process does not execute wait () at this time, the parent process will not capture the SIGCHLD signal, so the signal does not work,
The child process enters the transition state (if the parent process ignores SIGCHLD, the child process ends without entering the transition state ). This mechanism is very important for most UNIX programmers. In most cases, when a process receives a signal, it is terminated normally, which is equivalent to executing a temporary exit () call. In this case, the parent process can know what may happen from the exit status returned by the process. The low 8 bits in the exit status contain signal numbers, and the high 8 bits are 0.
Signal SIGQUIT, SIGILL, SIGTRAP, SIGSYS, and SIGFPEWill cause Abnormal TerminationThe memory image of the process is written into the core file in the current directory of the process. The core file records the value of all variables, the value of the hardware register, and the control information in the kernel at the time of termination in binary form. The exit status of an abnormal termination process is the same as that of the normal termination of the signal except that the low-end 7th-bit is set.
The Linux debugging program gdb knows the format of core files and can be used to observe the status of processes on the transition storage point. In this way, you can use gdb to correctly determine the location where the problem occurs.
Here we will introduce the system call abort (), which is defined in the Linux system library stdlib. h:
Void abort (void); // In fact, abort calls raise () to send signals to itself;
Abort () sends a signal to the calling process to generate an abnormal termination, that is, the core is switched to storage. Because it enables a process to record the current state of the process when an error occurs, it can be used as an auxiliary means of debugging. This also demonstrates the fact that a process can send signals to itself.

UNIX systems call signal () to receive a specified type of signal and specify the corresponding method. This means that signal () can associate the specified processing function with the signal direction. The function declaration in the Linux system library signal. h is as follows:
Int signal (int sig, _ sighandler_t handler );
Signal () has two parameters:
The first sig parameter specifies the signal type to be processed.Besides SIGKILL and SIGSTOPAny other signal. The handler parameter describes the action associated with the signal. It can take the following three values:

1. A function address without return values.

Void func (int sig );

2. SIG_IGN
This symbol indicates that the signal is ignored. After the corresponding signal () call is executed, the signal of Type sig is ignored.
3. SIG_DFL
This symbol indicates the default signal processing by the recovery system.

The correlation between signals and functions set in the parent process will be automatically restored to the default system action with SIG_DFL by exec, this is because there is no function image of the parent process in the exec sub-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","10",NULL);}else{sleep(10);}return 0;}


Running result:./a. out

<Clt + c>

Test1

In Linux, when a signal processing function is executed, if the process receives the signal again, the signal will be automatically stored without interrupting the execution of the signal processing function, after the signal processing function is executed, call the corresponding processing function again. The following program demonstrates this point:

#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(10);   printf(“Program NORMAL ended.\n”);   return;}

Run the command. The result is as follows:
Interrupt set for SIGINT
<Ctrl + c>
Interrupt called
<Ctrl + c>
Func Ended
Interrupt called
Func Ended
Program NORMAL ended.
HoweverIf the process receivesOther types of SignalsThe execution of this 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(10);   printf(“Program NORMAL ended.\n”);   return;}

The result of executing this program is as follows:
Interrupt set for SIGINT
<Ctrl + c>
Interrupt called
<Ctrl + \>
Quit called
Quit ended.
Interrupt Func Ended.
Program NORMAL ended.

Sends signals between processes
A process processes signals sent by other processes by calling signal. At the same time, a process can also send signals to other processes. This operation is completed by the system calling kill. The function declaration of kill () in the linux system library signal. h is as follows:
Int kill (pid_t pid, int sig );
The pid parameter specifies the target process for sending the signal: it can be the process identifier (pid) of a process or the following values:
If the pid is zero, the signal is sent to all processes in the process group where the current process is located;
If the pid is-1, the signal is sent to all processes in the order of process identifiers from high to low (this process is restricted by the permissions of the current process );
If the pid is less than-1, the signal is sent to the ID that is the absolute value of the pidProcess GroupInAll processes.
It should be noted that a process does not send signals to any process. There is a restriction that normal user processes can only send signals to processes with the same user identifier. That is to say,A user's process cannot send signals to another user's process. Only root processes can send signals to any thread.
The sig parameter specifies the signal type sent. It can be any valid signal.
Because the process that calls kill () needs to wait until the identifier of the process to which the signal is sent, the sending of this signal is usually only between closely related processes, such as between parent and child processes.


The following is an example of using kill () to call the sending signal. This program establishes two processes and sends the signal SIGUSR1 to the other party to implement synchronization between them. Both processes are in an endless loop, and are paused before receiving signals from the other side. This is achieved through the system call pause (), which can suspend a program until a signal arrives, and then the process outputs Information and uses kill to send a signal to the other party. When the user presses the interrupt key, both processes will be terminated.

# Include <signal. h> int ntimes = 0; main () {int pid, ppid; int p_action (), c_action ();/* Set SIGUSR1 */signal (SIGUSR1, p_action); switch (pid = fork () {case-1:/* fork failed */perror ("synchro"); exit (1); case 0: /* sub-process module * // * set the SIGUSR1 */signal (SIGUSR1, c_action) of the sub-process./* obtain the identifier of the parent process */ppid = getppid (); for (;) {sleep (1); kill (ppid, SIGUSR1); pause () ;}/ * endless loop */break; default: /* parent process module */for (;) {pause (); sleep (1); kill (pid, SIGUSR1 );} /* endless loop */} p_action () {printf ("Patent caught signal # % d \ n", ++ ntimes);} c_action () {printf ("Child caught signal # % d \ n", ++ ntimes );}

The program running result is as follows:
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 special attention to the problem of root User execution, such as the following program:

# 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;} run under root permission, 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> the system calls alarm () and pause () 1. System Call alarm () is a simple and useful system call. It can create an alarm clock for a process, report to the program by signal. Alarm () is called in the Linux system function library unistd. the function declaration in h is as follows: unsigned int alarm (unsigned int seconds); the unique parameter of the function is seconds, which provides the timer time in seconds. When the time arrives, a sigarlm signal is sent to the system. </Strong> </span>
<Span style = "font-size: 18px; background-color: rgb (255,255,255);"> <strong> an alarm clock set by calling alarm, after <span style = "color: # ff0000;"> it is called through exec (), it will still be valid </span>. However, <span style = "color: # ff0000;"> after fork () is called, it becomes invalid in the sub-process </span>. To disable the specified alarm clock, you only need to call the alarm (): </strong> </span> with the zero parameter.
<Span style = "font-size: 18px; background-color: rgb (255,255,255);"> <strong> alarm (0) alarm () calls cannot accumulate. If you call alarm twice, the second call replaces the first call. However, the returned values of alarm are the remaining time of the previously set alarm clock. When you need to set a time limit for a job, you can use alarm () to call it. The basic method is: first call alarm () to set the alarm clock based on the time limit value, and then the process performs a job. If the process completes this operation within the specified time, it then calls alarm (0) to invalidate the alarm clock. If this task is not completed within the specified time, the process will be 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 calls pause (). The system calls pause () to suspend the invocation of the calling process until it receives a certain signal. The function declaration of pause () in the Linux system function library unistd. h is as follows: int pause (void); this call has no parameters. Its return value is always-1, and 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>

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.