📜  Unix 中的信号和陷阱(1)

📅  最后修改于: 2023-12-03 14:48:13.524000             🧑  作者: Mango

Unix 中的信号和陷阱

在 Unix 操作系统中,信号是一种处理异步事件的机制。当一个进程接收到一个信号时,可以选择忽略信号、执行默认操作或自定义操作。

常见的信号

Unix 操作系统中有许多不同的信号,下面是一些常见的信号:

  • SIGINT:键盘中断信号,通常由用户使用 Ctrl + C 触发。
  • SIGTERM:终止信号,用于请求一个进程正常退出。
  • SIGKILL:杀进程信号,用于立即终止一个进程。
  • SIGSEGV:段错误信号,通常由访问未分配内存或非法内存引起。
发送信号

可以使用 kill 命令向指定进程发送信号:

kill -<signal> <pid>

其中 <signal> 是信号名称或编号,<pid> 是进程 ID。

处理信号

程序员可以使用 signal 函数来注册信号处理程序,例如:

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

void sigint_handler(int signal) {
    printf("\nCaught SIGINT, exiting...\n");
    exit(0);
}

int main() {
    signal(SIGINT, sigint_handler);
    printf("Running...\n");
    while (1) {}
    return 0;
}

上述程序注册了一个 SIGINT 信号处理程序,当用户按下 Ctrl + C 时,程序将输出一条消息并退出。

还可以使用 sigaction 函数注册信号处理程序,它比 signal 更加可靠和灵活。

除了显示地处理信号外,进程还可以忽略某些信号或使用信号捕捉阻止某些系统调用被打断。这需要使用 sigprocmask 函数来设置信号掩码。

陷阱

在 Unix Shell 中,将某个命令放在圆括号中可以将该命令放在一个子 shell 中执行,而且在子 shell 中运行的变量不会影响父 shell 中的变量。例如:

(a=1; echo $a) # 输出 1
echo $a # 输出空

但是,子 shell 中定义的信号处理程序可能会影响父 shell。当子 shell 注册一个信号处理程序时,它实际上是将该处理程序安装到内核中。但是,当子 shell 退出时,它的处理程序并没有被卸载,可能会影响父 shell 中的信号处理。

因此,在使用子 shell 时,需要小心处理信号。