Lien000034
2014-10-29
1. Concept of Signal
The description of signals in Wikipedia is as follows:
In computer science, signals (English: Signals) are a restricted way of inter-process communication in UNIX, Unix-like, and other POSIX-compatible operating systems. It is an asynchronous notification mechanism to remind the process that an event has occurred. When a signal is sent to a process and the operating system interrupts the normal control process of the process, any non-atomic operation will be interrupted. If a process defines a signal processing function, it will be executed. Otherwise, the default processing function will be executed.
In this section, we can learn the following signal knowledge,
1. Signal: An asynchronous communication mechanism between Unix processes.
2. signal function: reminds the target process of an event and interrupts the normal control process of the target process.
3. Process Signal Processing: The target process can execute the default signal processing function, or execute a custom process signal processing program.
Each signal has a name that starts with a three-character Sig. For example, SIGABRT is a dead signal, which is generated when the process calls the abort function. Sigalrm is an alarm signal generated when the timer set by the alarm function times out. In Unix systems, these signals are defined in the header file <signal. h> and are expressed in a positive integer (signal number ). Run the command kill-L in shell to view all signals executed by the current system.
The UNIX system specifies that the kernel can perform the following three processing actions on the signal,
1. Ignore this signal. Two signals, sigkill and sigstop, cannot be ignored. These two signals provide a reliable method for the Super User to terminate or stop the process.
2. Execute the default system action. The default action for most signals is to terminate the process.
3. Capture signals and execute User-Defined processing functions.
2. Set the signal processing program
The UNIX system provides the signal function to set the signal processing program,
# Include <signal. h>
Void (* signal (INT signo, void (* func) (INT );
Returned value: if the signal is successful, the previous processing configuration is returned. If an error occurs, the sig_err is returned.
The value of func can be,
• Frequent sig_ign: displays this letter number to the inner core table (two letter numbers sigkill and sigstop cannot be ignored, and an error is reported when the signal function is called ).
• The constant sig_dfl indicates the default action of the signal.
• A function pointer indicates that the function is executed for processing when a signal occurs. This function is called a signal processing program. The signal processing function receives an int-type signal value parameter and has no return value.
The Return Value of the signal is also a function pointer pointing to the signal processing program before the signal.
Let's take an example,
#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <signal.h>static void sig_usr(int);intmain(void){ if (signal(SIGUSR1, sig_usr) == SIG_ERR) { printf("can‘t catch SIGUSR1: %s\n", strerror(errno)); exit(-1); } if (signal(SIGUSR2, sig_usr) == SIG_ERR) { printf("can‘t catch SIGUSR2: %s\n", strerror(errno)); exit(-1); } for (;;) { pause(); } exit(0);}static voidsig_usr(int signo){ if (signo == SIGUSR1) { printf("received SIGUSR1\n"); } else if (signo == SIGUSR2) { printf("received SIGUSR2\n"); } else { printf("received signal: %d\n", signo); }}
Signaldemo. c
The above signaldemo. C Program sets the signal processing program sig_usr for the signal SIGUSR1 and sigusr2. Then, the pause wait signal is cyclically called in the main process. The pause function suspends the calling process until a signal is captured,
# Include <unistd. h>
Int pause (void );
Returned value:-1, and errno is set to eintr
The pause function returns only when a signal processing program is executed and returned from it.
Compile the signaldemo. C program, generate and execute the signaldemo file,
lienhua34:demo$ gcc -o signaldemo signaldemo.clienhua34:demo$ ./signaldemo &[1] 3033lienhua34:demo$ kill -USR1 3033lienhua34:demo$ received SIGUSR1kill -USR2 3033lienhua34:demo$ received SIGUSR2kill 3033
Kill-usr1 3033 and kill-usr2 3033 indicate the SIGUSR1 and sigusr2 signals sent to processes with the process ID 3033 respectively, while kill 3033 indicates the sigterm signal sent to process 3033, this signal terminates the process.
The signal SIGUSR1 and sigusr2 are two user-defined signals defined by UNIX. A Unix system supports fixed signal types, and users cannot add new signal types. If you want to implement your own functions through the signal mechanism, you can use the signal processing program of the custom signal SIGUSR1 or sigusr2 to implement your desired functions. For example, in Wikipedia,
For example, the linuxthreads thread library in Linux 2.0 has been deprecated and replaced by nptl ). Other programs, such as some versions of DD, will output the current status when receiving the signal (DD Implementation of Mac OS X will be suspended when receiving usr1 ). Usr1 is also usually used to inform the application to reload the configuration file. For example, sending a usr1 signal to the Apache HTTP Server will lead to the following steps: stop accepting new connections and wait until the current connection stops, reload the configuration file, re-open the log file, and restart the server to achieve smooth and non-Shutdown changes.
3. send signals to processes
The UNIX system provides two functions: Kill and raise to generate signals. The kill function sends signals to a specified process or process group. The raise function allows a process to send signals to itself.
# Include <signal. h>
Int kill (pid_t PID, int signo );
Int raise (INT signo );
Two function return values: 0 if successful, and-1 if an error occurs
Calling raise (signo) is equivalent to kill (getpid (), signo ).
The PID parameters of the kill function have four different situations:
(1) pid> 0 sends the signal to the process whose ID is PID.
(2) pid = 0 sends signals to all processes in the same process group of the sending process, and the sending process has the permission to send signals to these processes.
(3) PID <0 sends signals to all processes whose process group ID is equal to the absolute value of PID, And the sending process has the permission to send signals to these processes.
(4) pid =-1 send signals to all processes on the system where the sender has the permission to send signals to them.
There are two points to note: (1) "all processes" do not include the system process set; (2) the sending process is a superuser, or the actual or valid user ID of the sending process is equal to the actual or valid user ID of the receiving process. The following is an example,
#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <signal.h>#include <unistd.h>static void sig_usr(int);intmain(void){ pid_t pid; if (signal(SIGUSR1, sig_usr) == SIG_ERR) { printf("can‘t catch SIGUSR1: %s\n", strerror(errno)); exit(-1); } if (signal(SIGUSR2, sig_usr) == SIG_ERR) { printf("can‘t catch SIGUSR2: %s\n", strerror(errno)); exit(-1); } if ((pid = fork()) < 0) { printf("fork error: %s\n", strerror(errno)); exit(-1); } else if (pid == 0) { pause(); exit(0); } printf("process %d creates a child process %d\n", getpid(), pid); sleep(1); kill(pid, SIGUSR1); waitpid(pid, NULL); raise(SIGUSR2); exit(0);}static voidsig_usr(int signo){ if (signo == SIGUSR1) { printf("process %d received SIGUSR1\n", getpid()); } else if (signo == SIGUSR2) { printf("process %d received SIGUSR2\n", getpid()); } else { printf("process %d received signal: %d\n", getpid(), signo); }}
Killdemo. c
In the preceding killdemo. C program file, the parent process sets the signal processing program sig_usr for the signal SIGUSR1 and sigusr2. Then call fork to create a sub-process. The signal processing programs of the sub-process signal SIGUSR1 and sigusr2 inherit from the parent process, which is also sig_usr (unless the sub-process calls the exec function, the signal processing actions of the two signals in the sub-process will be set to the system default ). The parent process calls the kill function to send the signal SIGUSR1 to the child process, and calls the raise function to send the signal sigusr2. compile the program, generate and execute the killdemo file,
lienhua34:demo$ ./killdemoprocess 3261 creates a child process 3262process 3261 received SIGUSR2process 3262 received SIGUSR1
Through the above running results, we can see that the parent process 3261 has created the sub-process 3262, the parent process 3261 has captured the signal sigusr2, and the child process has captured the signal SIGUSR1. The actual running result is consistent with the expected result.
(Done)
Unix programming learning notes (23) -- initial learning of Signal Processing