1. In order to understand the signal, let's start with the scenario we are most familiar:
1. Enter a command to start a foreground process in shell.
2. Press ctrl-C to cause a hardware interruption.
3. If the CPU is currently executing the code of the process, the user space code of the process is suspended, and the CPU switches from user State to kernel state to process hardware interruption.
4. The Terminal Driver interprets Ctrl-C as a SIGINT signal and records it in the PCB of the process (it can also be said that a SIGINT signal is sent to the process ).
5. when the user space code returned from the kernel to the process continues to be executed at a certain time point, the signal recorded in the PCB is first processed and a SIGINT signal is found to be waiting for processing, the default processing action of this signal is to terminate the process, so the process is terminated directly without returning its user space code for execution.
Use the kill-l command to view the system-defined signal list:
Each signal has a number and a macro definition name, which can be found in signal. H. For example, there is a definition # define SIGINT 2. If the number is greater than 34, it indicates the real-time signal under which the signals are generated, and the default processing action (term indicates that the current process is terminated, core indicates that the current process is terminated, and core dump, IGN indicates that the signal is ignored, stop indicates that the current process is stopped, and cont indicates that the previously stopped process is continued), which is described in detail in signal (7.
0 ~ 31. If the signal is unreliable, multiple signals will not be retained in line, meaning that the signal may be lost.
34 ~ 64 reliable (real-time signal), supporting no loss of queuing signals, you can use sigqueue to send signals, unlike 0 ~ 31 has a default definition.
2. Main conditions for generating signals include:
1. When you press some keys on the terminal, the terminal driver sends a signal to the foreground process. For example, Ctrl-C generates a SIGINT signal and Ctrl-\ generates a sigquit signal, CTRL-Z generates the sigtstp signal.
2. Hardware exceptions generate signals. These conditions are detected by the hardware and notified to the kernel. Then, the kernel sends appropriate signals to the current process. For example, if the current process executes a command divided by 0, an exception occurs in the CPU computing unit. The kernel interprets this exception as a sigfpe signal sent to the process.
3. For example, if the current process accesses an invalid memory address, MMU will generate an exception. The kernel interprets this exception as a SIGSEGV signal sent to the process.
4. A process can call the kill (2) function to send signals to another process.
5. You can use the kill (1) command to send a signal to a process. The kill (1) command is also implemented by calling the kill (2) function. If the signal is not explicitly specified, the sigterm signal is sent, the default processing action for this signal is to terminate the process.
6. Raise: send a signal to yourself. Raise (SIG) is equivalent to kill (getpid (), sig );
7. killpg: sends a signal to the process group. Killpg (pgrp, sig) is equivalent to kill (-pgrp, sig );
8. sigqueue: sends signals to processes. It supports queuing and can contain additional information.
9. When the kernel detects a software condition, it can also send a signal to the process. For example, the alarm clock times out to generate a sigalrm signal, and the sigpipe signal is generated when writing data to the closed pipeline on the read end.
3. the user program can call the signal (2)/sigaction (2) function to tell the kernel how to process a certain signal (if not registered, it will be processed by default). There are three optional processing actions:
1. Ignore this signal. Two signals cannot be ignored: sigkill and sigstop.
2. Execute the default processing action for this signal.
3. Provides a signal processing function that requires the kernel to switch to the user State to execute the processing function when processing the signal. This method is called catch.
Iv. Differences between signals and interruptions
Signal and interrupt similarity:
(1) adopts the same asynchronous communication mode;
(2) When a signal or interrupt request is detected, all processes being executed are suspended and transferred to execute the corresponding processing procedures;
(3) All returned to the original breakpoint after processing;
(4) shielding of signals or interruptions.
Differences between signals and interruptions:
(1) The interruption has a priority, but the signal has no priority. All signals are equal;
(2) The signal processing program runs in the user State, while the interrupt processing program runs in the core State;
(3) The interrupt response is timely, and the signal response usually has a large time delay.
5. Signal (2) signal registration function
Typedef void (* _ sighandler_t) (INT );
# Define sig_err (_ sighandler_t)-1)
# Define sig_dfl (_ sighandler_t) 0)
# Define sig_ign (_ sighandler_t) 1)
Function prototype:
_ Sighandler_t signal (int signum, _ sighandler_t handler );
Parameters
Signal is a function with SIGNUM and handler parameters. signals to be captured or blocked are provided by the SIGNUM parameter. The function to be called when a specified signal is received is provided by handler, the handler function must have an int type parameter (that is, the received signal code). Its own type is void.
Handler can also have two special values: sig_ign to shield the signal; sig_dfl to restore default behavior
Return Value
Signal () returns the previous value of the signal handler, or sig_err on error.
Sample Applet:
C ++ code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
/*************************************** ********************************** > File name: Process _. c > Author: Simba > Mail: dameng34@163.com > Created time: sat 23 Feb 2013 02:34:02 pm CST **************************************** ********************************/ # Include <sys/types. h> # Include <sys/STAT. h> # Include <unistd. h> # Include <fcntl. h> # Include <stdio. h> # Include <stdlib. h> # Include <errno. h> # Include <string. h> # Include <signal. h># Define err_exit (m )\ Do {\ Perror (m );\ Exit (exit_failure );\ } While (0) Void handler (INT sig ); Int main (INT argc, char * argv []) { _ Sighandler_t oldhandler; Oldhandler = signal (SIGINT, Handler); // The returned value is the previous signal handler function pointer. If (oldhandler = sig_err) Err_exit ("signal error "); While (getchar ()! = '\ N '); /* Signal (SIGINT, sigdfl )*/ If (signal (SIGINT, oldhandler) = sig_err) Err_exit ("signal error "); For (;;); Return 0; } Void handler (INT sig) { Printf ("Recv a Sig = % d \ n", sig ); } |
The test output is as follows:
Simba @ Ubuntu :~ /Documents/code/linux_programming/apue/signal $./signal
^ Crecv a Sig = 2
^ Crecv a Sig = 2
^ Crecv a Sig = 2
^ C
Simba @ Ubuntu :~ /Documents/code/linux_programming/apue/signal $
The program execution starts to register the processing function of the SIGINT signal. Therefore, pressing CTRL + C does not terminate the program as usual, but only prints Recv a Sig = 2. Press enter and re-register the default SIGINT processing. Then, the CTRL + C program is terminated.
Replace the 32 ~ Replace line 37 with the following statement:
C ++ code
1 2 3 4 5 6 7 |
|
For (;;) { Pause (); // suspends the process until a signal is captured (returned after the signal processing function is complete) // Call schedule () to schedule other programs, // The advantage of this method over a completely endless loop is that the CPU Printf ("Pause return \ n "); } |
Call the pause function to set the process to an interrupted sleep state. Then it calls schedule () so that the Linux Process scheduler can find another process to run. PAUSE Suspends the caller process until a signal is captured and processed before the function returns. The advantage of calling pause is to give up the CPU while waiting for the signal, so that the system Schedules other processes to run, rather than completely endless loops. Of course, CTRL + C will never terminate the program, we can use Ctrl + \ to generate a sigquit signal to terminate the program.
In fact, according to the man manual, the signal function is not very portable. It is best to use it only on sig_dfl and sig_ign. It is better to use sigaction to register the signal processing function.
Reference: apue and Linux C Programming one-stop learning