Signals are software interrupts that provide a mechanism for handling asynchronous events. These events can originate from outside the system, such as when the user gen‐erates the interrupt character by pressing Ctrl-C, or from activities within the program or kernel, such as when the process executes code that divides by zero. As a primitive form of interprocess communication (IPC), one process can also send a signal to another process.
信号是一种软件中断,它提供了一种处理异步事件的机制......
The key point is not just that the events occur asynchronously—the user, for example, can press Ctrl-C at any point in the program’s execution—but also that the program handles the signals asynchronously. The signal-handling functions are registered with the kernel, which invokes the functions asynchronously from the rest of the program when the signals are delivered.
不仅仅信号的发送是异步的,信号的处理也是异步的....
1. 基础信号处理注册函数
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal (int signo, sighandler_t handler);
给信号signo注册一个处理器handler。
信号表
2. 等待信号
#include <unistd.h>
int pause (void);
pause() returns only if a signal is received, in which case the signal is handled, and pause() returns −1 and sets errno to EINTR. If the kernel raises an ignored signal, the process does not wake up.
只有接收到信号时pause()才会返回,当信号被处理时,pause()返回-1并且设置errno为EINTR,当发出的信号是被忽略信号时,进程并不会醒来。
==>例程:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
/* handler for SIGINT */
static void sigint_handler (int signo)
{
/*
* Technically, you shouldn't use printf() in a
* signal handler, but it isn't the end of the
* world. I'll discuss why in the section
* "Reentrancy."
*/
printf ("Caught SIGINT!\n");
exit (EXIT_SUCCESS);
}
int main (void)
{
/*
* Register sigint_handler as our signal handler
* for SIGINT.
*/
if (signal (SIGINT, sigint_handler) == SIG_ERR) {
fprintf (stderr, "Cannot handle SIGINT!\n");
exit (EXIT_FAILURE);
}
for (;;)
pause ();
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
/* handler for SIGINT and SIGTERM */
static void signal_handler (int signo)
{
if (signo == SIGINT)
printf ("Caught SIGINT!\n");
else if (signo == SIGTERM)
printf ("Caught SIGTERM!\n");
else {
/* this should never happen */
fprintf (stderr, "Unexpected signal!\n");
exit (EXIT_FAILURE);
}
exit (EXIT_SUCCESS);
}
int main (void)
{
/*
* Register signal_handler as our signal handler
* for SIGINT.
*/
if (signal (SIGINT, signal_handler) == SIG_ERR) {
fprintf (stderr, "Cannot handle SIGINT!\n");
exit (EXIT_FAILURE);
}
/*
* Register signal_handler as our signal handler
* for SIGTERM.
*/
if (signal (SIGTERM, signal_handler) == SIG_ERR) {
fprintf (stderr, "Cannot handle SIGTERM!\n");
exit (EXIT_FAILURE);
}
/* Reset SIGPROF's behavior to the default. */
if (signal (SIGPROF, SIG_DFL) == SIG_ERR) {
fprintf (stderr, "Cannot reset SIGPROF!\n");
exit (EXIT_FAILURE);
}
/* Ignore SIGHUP. */
if (signal (SIGHUP, SIG_IGN) == SIG_ERR) {
fprintf (stderr, "Cannot ignore SIGHUP!\n");
exit (EXIT_FAILURE);
}
for (;;)
pause ();
return 0;
}
4. 将信号转换为字符串描述
extern const char * const sys_siglist[];
#define _GNU_SOURCE
#include <string.h>
char * strsignal (int signo);
sys_siglist is an array of strings holding the names of the signals supported by the system, indexed by signal number.
strsignal()函数返回的结果的有效期是下一次strsignal()函数的调用。
5. 发送一个信号到某个进程
#include <sys/types.h>
#include <signal.h>
int kill (pid_t pid, int signo);
pid
If pid is 0, signo is sent to every process in the invoking process’s process group.如果pid为0,信号将发送到进程所在进程组中的所有进程
If pid is −1, signo is sent to every process for which the invoking process has permission to send a signal, except itself and init.
如果pid为-1,信号将发送到所有其有权限发送信号的进程,除了init进程和本身。
If pid is less than −1, signo is sent to the process group -pid.
如果pid小于-1,信号将发送到进程组为|pid|的所有进程。
6. 权限
In order to send a signal to another process, the sending process needs proper permissions. A process with the CAP_KILL capability (usually one owned by root) can send a signal to any process. Without this capability, the sending process’s effective or real user ID must be equal to the real or saved user ID of the receiving process. Put more simply,a user can send a signal only to a process that he or she owns.
7. 发送信号到自身的简单方法
#include <signal.h>
int raise (int signo);
8. 未完待继......