📅  最后修改于: 2023-12-03 14:59:47.939000             🧑  作者: Mango
信号处理(Signal Handling)是指在程序运行中,应用程序接收到来自操作系统的信号,并作出相应的处理。在Unix类系统中,信号是一种可以被操作系统传递给进程的软件中断,用于通知进程发生了某些事件。使用信号处理,可以实现对进程的控制,达到优雅退出、异常处理等目的。
使用系统调用signal()
可以指定一个信号处理器来处理特定信号的接收。
#include <iostream>
#include <csignal>
void signal_handler(int signum){
std::cout<<"Received signal: "<<signum<<std::endl;
}
int main(){
// 注册SIGINT信号处理器
signal(SIGINT, signal_handler);
// 死循环
while(1);
return 0;
}
除了可读性更好外,可以看到我们要处理的信号SIGINT
被和处理函数signal_handler
绑定到了一起。当在运行程序的终端中按下Ctrl+C
键时,会输出Received signal: 2
,表示程序已经收到了SIGINT
信号。
我们也可以使用sigprocmask()
系统调用来阻塞一个或多个信号,使得这些信号在阻塞期间不会被处理程序接收。
#include <iostream>
#include <csignal>
#include <unistd.h>
void signal_handler(int signum){
std::cout<<"Received signal: "<<signum<<std::endl;
}
int main(){
sigset_t blockset, tempset;
sigemptyset(&blockset); // 清空信号阻塞集
sigaddset(&blockset, SIGINT); // 将SIGINT信号添加到阻塞集
// 阻塞SIGINT信号
sigprocmask(SIG_BLOCK, &blockset, &tempset);
std::cout<<"Blocked SIGINT signal!"<<std::endl;
// 休眠20s
sleep(20);
// 取消阻塞SIGINT信号
sigprocmask(SIG_SETMASK, &tempset, NULL);
std::cout<<"Unblocked SIGINT signal!"<<std::endl;
// 死循环
while(1);
return 0;
}
在程序开始时,我们创建了一个信号阻塞集blockset
,将SIGINT
信号添加到其中。接着,我们调用sigprocmask()
函数来将阻塞集中的信号阻塞,使得在接下来的20s内不会接收到SIGINT
信号,并输出Blocked SIGINT signal!
。之后,恢复原信号屏蔽位,重新接收SIGINT
信号,并输出Unblocked SIGINT signal!
。
使用kill()
系统调用可以向指定进程内发送指定信号。
#include <iostream>
#include <csignal>
#include <unistd.h>
#include <sys/types.h>
void signal_handler(int signum){
std::cout<<"Received signal: "<<signum<<std::endl;
}
int main(){
pid_t pid = getpid();
std::cout<<"Main process PID: "<<pid<<std::endl;
// 注册SIGUSR1信号处理器
signal(SIGUSR1, signal_handler);
// 休眠3s
std::cout<<"Sleeping for 3s..."<<std::endl;
sleep(3);
// 向本进程发送SIGUSR1信号
kill(pid, SIGUSR1);
std::cout<<"Sent SIGUSR1 signal to process "<<pid<<"!"<<std::endl;
// 死循环
while(1);
return 0;
}
程序开始运行时,先获取本程序的PID,并输出,之后注册SIGUSR1
信号处理器。在休眠3s后,使用kill()
函数向本进程发送SIGUSR1
信号,并输出发送成功的信息。在程序运行过程中,可以在终端中使用kill -USR1 [PID]
命令来模拟发送SIGUSR1
信号。