image-20240420163459407

信号处理程序

在Unix和类Unix系统中,信号是一种用于进程间通信的机制,用于通知进程发生了某种事件或异常情况。

例如,进程可以接收到SIGINT信号表示用户按下了终止键(通常是Ctrl+C),SIGSEGV信号表示进程发生了段错误等。每个信号都有一个对应的编号,可以在<signal.h>头文件中找到相应的定义。

信号处理程序可以通过以下步骤来设置和使用:

注册信号处理程序:进程可以使用signal()函数或者更推荐的sigaction()函数来注册信号处理程序。注册时需要指定要处理的信号以及对应的处理函数。

处理信号:当进程接收到注册的信号时,操作系统会自动调用相应的信号处理程序。处理程序可以是预定义的系统默认处理方式,也可以是进程自定义的处理逻辑。

执行处理逻辑:信号处理程序可以执行各种操作,例如终止进程、忽略信号、执行特定的操作逻辑、发送信号给其他进程等。

常见的信号处理函数包括:

SIG_DFL:默认处理程序,由系统提供的默认处理逻辑。

SIG_IGN:忽略信号,告诉系统在接收到指定信号时不采取任何操作。

自定义处理函数:进程可以编写自己的信号处理函数,以处理特定信号发生时的操作逻辑。

通过信号处理程序,进程可以对接收到的信号进行处理,从而实现对进程的控制、异常处理、资源清理等操作,增强了程序的稳定性和可靠性。

1. 信号处理程序的注册

信号处理程序的注册可以使用signal()函数或者sigaction()函数来实现。

signal()函数的原型如下:

void (*signal(int signum, void (*handler)(int)))(int);

其中,signum表示要处理的信号编号,handler表示信号处理函数的指针。signal()函数的返回值是一个函数指针,指向之前注册的信号处理函数。

2. 服务端开发经常需要屏蔽一些信号

SIGINT信号

SIGINT信号是在用户按下终止键(通常是Ctrl+C)时,内核会向进程发送SIGINT信号,通知进程终止。如果进程不处理SIGINT信号,那么进程会被终止。

SIGQUIT信号

SIGQUIT信号是在用户按下退出键(通常是Ctrl+\)时,内核会向进程发送SIGQUIT信号,通知进程终止。与SIGINT信号不同的是,SIGQUIT信号会在终止进程时生成一个core文件,用于调试进程。

SIGTSTP信号

SIGTSTP信号是在用户按下挂起键(通常是Ctrl+Z)时,内核会向进程发送SIGTSTP信号,通知进程挂起。如果进程不处理SIGTSTP信号,那么进程会被挂起。

SIGCHLD信号

SIGCHLD信号是在子进程终止或停止时,内核会向父进程发送SIGCHLD信号,通知父进程子进程的状态发生了变化。父进程可以通过捕获SIGCHLD信号来回收子进程的资源。

SIGPIPE信号

SIGPIPE信号是在进程向一个已经收到RST的socket连接写数据时,内核会向进程发送SIGPIPE信号,通知进程对方已经关闭连接。如果进程不处理SIGPIPE信号,那么进程会被终止。

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

void sig_handler(int signo) {
if (signo == SIGPIPE) {
printf("received SIGPIPE\n");
}
}

int main() {
signal(SIGPIPE, sig_handler);

return 0;
}

SIGSYS信号

SIGSYS信号是在进程执行了一个无效的系统调用时,内核会向进程发送SIGSYS信号,通知进程发生了系统调用错误。如果进程不处理SIGSYS信号,那么进程会被终止。