信号(Signal)

在 Linux 系统中,信号(Signal) 是一种用于进程间通信的机制,它允许操作系统和进程之间传递通知,告知进程发生了某些事件。信号通常由内核生成,或者由其他进程发送。

信号的基本概念

信号是一种异步通知,它会中断正在运行的进程,并对其进行某种处理。信号机制是多进程环境下的一种重要通信手段,可以用于控制进程的行为(如终止进程、暂停进程、重新加载配置等)。

常见的信号

信号名称信号编号描述
SIGHUP 1 终端挂起,通常用于通知进程重新加载配置。
SIGINT 2 中断信号,通常由 Ctrl+C 触发,终止正在运行的进程。
SIGQUIT 3 退出信号,通常由 Ctrl+\ 触发,进程退出并产生核心转储文件。
SIGILL 4 非法指令,进程试图执行无效或非法的机器指令。
SIGABRT 6 异常终止信号,进程调用 abort() 函数时触发。
SIGFPE 8 浮点运算错误,例如除以零。
SIGKILL 9 强制终止进程,无法被捕获或忽略。
SIGSEGV 11 段错误,通常是由于非法访问内存(如访问已释放的内存)引起的。
SIGPIPE 13 管道破裂,当向一个没有读端的管道写数据时会触发。
SIGALRM 14 定时器信号,通常由 alarm() 函数设置的定时器触发。
SIGTERM 15 终止信号,默认的终止进程信号,进程可以捕获并做清理操作。
SIGUSR1 10 用户定义信号 1,可以被应用程序使用来执行自定义操作。
SIGUSR2 12 用户定义信号 2,通常被应用程序用于自定义处理。
SIGCHLD 17 子进程终止信号,父进程会接收到此信号以响应子进程的退出。
SIGSTOP 19 停止信号,暂停进程的执行,无法被捕获或忽略。
SIGCONT 18 继续执行信号,用于恢复被暂停的进程。

信号的处理

  1. 默认行为
    • 每个信号都有一个默认行为。例如,SIGTERM 默认终止进程,SIGSTOP 默认暂停进程。
  2. 信号的捕获
    • 进程可以通过设置信号处理程序来捕获并处理某些信号。进程可以决定是忽略信号,还是执行自定义的操作。
  3. 信号的阻塞与解除阻塞
    • 进程可以选择阻塞某些信号,避免信号在进程执行过程中中断。阻塞信号后,信号会在进程解除阻塞时传递。

信号的发送

信号可以通过以下几种方式发送:

  1. 由操作系统自动发送

    • 例如,SIGSEGV 是因为访问非法内存地址而自动发送的。
  2. 由其他进程通过系统调用发送

    • 使用 kill() 系统调用,可以发送信号到指定的进程。例如:
      bash
      kill -SIGTERM <pid>
    • kill() 命令发送的信号不仅限于 SIGTERM,你也可以指定其他信号。
  3. 由程序通过函数发送

    • 使用 raise()kill() 函数,程序可以发送信号到自身或其他进程:
      c
      raise(SIGTERM); // 发送 SIGTERM 信号给当前进程

信号的捕获与处理

进程可以捕获并处理信号。可以使用 signal() 函数来指定处理某个信号的函数。处理信号的函数称为 信号处理程序

示例:捕获 SIGINT 信号

c
复制代码
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

void handle_sigint(int sig) {
printf("Caught signal %d\n", sig);
exit(0); // 退出进程
}

int main() {
signal(SIGINT, handle_sigint); // 捕获 SIGINT 信号并调用 handle_sigint
while (1) {
printf("Waiting for signal...\n");
sleep(1);
}
return 0;
}
复制代码

 

在这个例子中,当按下 Ctrl+C(发送 SIGINT 信号)时,程序将捕获到信号并执行 handle_sigint() 函数。

注意

  • 在现代的 Linux 系统中,使用 sigaction()signal() 更为推荐,因为它更为强大和灵活。

信号的阻塞与解除阻塞

可以使用 sigprocmask() 函数来阻塞或解除阻塞信号。例如,阻塞 SIGINT 信号:

c
复制代码
#include <signal.h>

int main() {
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    
    sigprocmask(SIG_BLOCK, &set, NULL);  // 阻塞 SIGINT 信号
    
    // 这里的代码会继续执行,直到解除阻塞
    
    return 0;
}
复制代码

 

常用的信号操作函数

  • signal(): 设置信号处理函数。
  • sigaction(): 设置更详细的信号处理规则(推荐使用)。
  • raise(): 发送信号到当前进程。
  • kill(): 向其他进程发送信号。
  • sigprocmask(): 控制信号的阻塞与解除。
  • sigpending(): 检查哪些信号已被发送但尚未处理。
  • sigwait(): 等待一个或多个信号的发生。

总结

  • 信号是 Linux 系统中一种重要的进程间通信和控制机制。
  • 它可以用于通知进程发生了某些事件(例如终止、暂停、错误等)。
  • 可以通过 signal()sigaction() 函数来捕获和处理信号。
  • 信号也可以被阻塞、忽略或发送到其他进程。
  • 理解信号机制对于编写健壮的多进程应用非常重要,尤其是在系统级编程中。
posted @   大帅。  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示