Skip to content

1. 信号的概念:

信号是用于进程间通信的一种机制,它是一种软件中断,用来通知进程发生了某个事件。当某个进程需要与另一个进程进行交互或者处理某些特殊情况时,可以发送一个信号给目标进程。

常见的信号类型包括:

  • SIGHUP(挂起信号)
  • SIGINT(中断信号)
  • SIGQUIT(退出信号)
  • SIGILL(非法指令信号)
  • SIGABRT(异常终止信号)
  • SIGFPE(浮点异常信号)
  • SIGKILL(强制退出信号)
  • SIGSEGV(段错误信号)
  • SIGPIPE(管道破裂信号)
  • SIGTERM(终止信号)

还有其他信号,共计约 64 种,每个信号都有一个唯一的编号和名称。

2. 64种信号量及其详细解释:

下面是64种信号量及其详细解释的Markdown表格:

信号编号信号名称说明
1SIGHUP挂起信号。通常由终端断开或退出导致。
2SIGINT中断信号。通常由用户在终端上按下Ctrl+C触发。
3SIGQUIT退出信号。通常由用户在终端上按下Ctrl+\触发。
4SIGILL非法指令信号。当进程执行了一个非法指令时,操作系统会发送该信号给进程。
5SIGTRAP跟踪陷阱信号。当进程收到调试命令时,操作系统会发送该信号给进程。
6SIGABRT异常终止信号。由调用abort()函数产生,表示进程非正常终止。
7SIGBUS总线错误信号。当进程执行了一个内存访问错误时,操作系统会发送该信号给进程。
8SIGFPE浮点异常信号。当进程执行一个浮点运算错误时,会收到该信号。
9SIGKILL强制退出信号。无法被忽略、捕获或阻塞,用于立即终止进程。
10SIGUSR1用户自定义信号1。用于在进程间自定义通信。
11SIGSEGV段错误信号。当进程访问了一个无效的内存地址或进行了无效的内存操作时,会收到该信号。
12SIGUSR2用户自定义信号2。用于在进程间自定义通信。
13SIGPIPE管道破裂信号。当进程向一个已关闭的管道进行写操作时,会收到该信号。
14SIGALRM闹钟信号。通常由调用alarm()函数设置的定时器超时触发。
15SIGTERM终止信号。通常用于请求进程正常终止。
16SIGSTKFLT协处理器堆栈错误信号。当协处理器执行了一个堆栈错误指令或检测到堆栈错误时,操作系统会发送该信号给进程。
17SIGCHLD子进程状态改变信号。当一个进程的子进程停止或退出时,父进程会收到该信号。
18SIGCONT继续执行信号。用于恢复之前被暂停的进程的执行。
19SIGSTOP停止执行信号。无法被忽略、捕获或阻塞,用于暂停进程的执行。
20SIGTSTP终端停止信号。通常由用户在终端上按下Ctrl+Z触发,用于暂停前台进程的执行。
21SIGTTIN后台进程读写终端的信号。当一个后台进程尝试读取终端时,会收到该信号。
22SIGTTOU后台进程读写终端的信号。当一个后台进程尝试写入终端时,会收到该信号。
23SIGURG紧急数据信号。表示接收到了带外数据。
24SIGXCPUCPU时间限制信号。当进程超过了预设的CPU时间限制时,会收到该信号。
25SIGXFSZ文件大小限制信号。当进程超过了预设的文件大小限制时,会收到该信号。
26SIGVTALRM虚拟定时器信号。通常由调用setitimer()函数设置的虚拟定时器超时触发。
27SIGPROF专用定时器信号。通常由调用setitimer()函数设置的专用定时器超时触发。
28SIGWINCH窗口大小改变信号。当终端窗口大小发生改变时,会收到该信号。
29SIGIO异步I/O信号。表示I/O操作可以进行。
30SIGPWR电源故障信号。当检测到系统电源故障时,会发送该信号。
31SIGSYS非法系统调用信号。当进程执行了一个非法的系统调用时,会收到该信号。
32SIGBABY进程变更信号。当一个进程成为另一个进程的子进程时,会收到该信号。
33SIGEMTEMT指令信号。当进程执行了一个EMT指令时,会收到该信号。
34SIGSTKFLT协处理器堆栈错误信号。当协处理器执行了一个堆栈错误指令或检测到堆栈错误时,操作系统会发送该信号给进程。
35SIGIO异步I/O信号。表示I/O操作可以进行。
36SIGCLD旧式的子进程状态改变信号。与SIGCHLD相同。
37SIGPOLLPollable事件信号。与SIGIO相同。
38SIGSTOP停止执行信号。无法被忽略、捕获或阻塞,用于暂停进程的执行。
39SIGTSTP终端停止信号。通常由用户在终端上按下Ctrl+Z触发,用于暂停前台进程的执行。
40SIGCONT继续执行信号。用于恢复之前被暂停的进程的执行。
41SIGCHLD子进程状态改变信号。当一个进程的子进程停止或退出时,父进程会收到该信号。
42SIGTTIN后台进程读写终端的信号。当一个后台进程尝试读取终端时,会收到该信号。
43SIGTTOU后台进程读写终端的信号。当一个后台进程尝试写入终端时,会收到该信号。
44SIGIO异步I/O信号。表示I/O操作可以进行。
45SIGXCPUCPU时间限制信号。当进程超过了预设的CPU时间限制时,会收到该信号。
46SIGXFSZ文件大小限制信号。当进程超过了预设的文件大小限制时,会收到该信号。
47SIGVTALRM虚拟定时器信号。通常由调用setitimer()函数设置的虚拟定时器超时触发。
48SIGPROF专用定时器信号。通常由调用setitimer()函数设置的专用定时器超时触发。
49SIGWINCH窗口大小改变信号。当终端窗口大小发生改变时,会收到该信号。
50SIGINFO信息请求信号。Symbolic常为SIGPWR,与SIGPWR相同。
51SIGUSR1用户自定义信号1。用于在进程间自定义通信。
52SIGUSR2用户自定义信号2。用于在进程间自定义通信。
53SIGTHRThread信号。用于线程的中断和终止。
54-59保留
60SIGLWPLight-weight process信号。用于LWP线程的中断和终止。
61-63保留

3. 信号的产生:

信号可以由多种事件和操作产生。常见的方式包括:

  • 用户通过按键组合,如 Ctrl+C 发送 SIGINT 信号给前台进程。
  • 用户通过终端按下 Ctrl+\ 发送 SIGQUIT 信号给前台进程。
  • 操作系统将某个特定的信号发送给进程,例如 SIGHUP 表示终端断开连接,SIGALRM 表示闹钟定时器到期等。

4. 信号的注册和注销:

进程可以使用 signal 函数来注册信号处理程序,用于捕获并处理特定信号。示例代码如下所示:

c
#include <stdio.h>
#include <signal.h>

void sig_handler(int signum) {
    // 处理特定信号的逻辑
    printf("Received signal: %d\n", signum);
}

int main() {
    // 注册信号处理程序
    signal(SIGINT, sig_handler);

    // 执行其他操作

    // 注销信号处理程序
    signal(SIGINT, SIG_DFL);

    return 0;
}

在上述示例中,通过调用 signal 函数来注册 SIGINT 信号的处理程序 sig_handler。当收到 SIGINT 信号时,会执行 sig_handler 函数中定义的逻辑。如果不再需要处理该信号,可以使用 signal 函数将处理程序设置为默认行为(SIG_DFL)。

5. 信号的处理:

进程收到一个信号时,可以按照以下方式进行处理:

  • 忽略信号:使用 signal 函数将信号处理程序设置为 SIG_IGN,表示忽略该信号。
  • 捕获并处理信号:使用 signal 函数将信号处理程序设置为自定义的信号处理函数,用于捕获并处理特定信号。
  • 执行默认行为:使用 signal 函数将信号处理程序设置为 SIG_DFL,表示执行信号的默认行为。

需要注意的是,有些信号无法被忽略或捕获,如 SIGKILL 和 SIGSTOP。这些信号被用于强制退出进程和暂停进程的执行。

Released under the MIT License.