在Linux系统中,进程信号的捕捉和处理是进程管理的重要组成部分。信号是操作系统用来通知进程发生了某种事件的一种机制。以下是Linux进程信号捕捉和处理的几种常见方式:
信号处理函数
进程可以通过设置信号处理函数来捕捉和处理信号。信号处理函数是一个用户定义的函数,当信号发生时,操作系统会调用该函数。使用signal
或sigaction
系统调用可以设置信号处理函数。
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void handle_signal(int signum) {
printf("Received signal %d\n", signum);
}
int main() {
signal(SIGINT, handle_signal);
while (1) {
printf("Waiting for signal...\n");
sleep(1);
}
return 0;
}
忽略信号
进程可以选择忽略某些信号,使其不产生任何效果。使用signal
系统调用并将处理函数设置为SIG_IGN
可以忽略信号。
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
signal(SIGINT, SIG_IGN);
while (1) {
printf("Ignoring SIGINT...\n");
sleep(1);
}
return 0;
}
默认处理
如果进程没有为信号设置处理函数,信号将按照默认行为处理。默认行为可能是终止进程、忽略信号或产生核心转储文件。使用signal
系统调用并将处理函数设置为SIG_DFL
可以恢复信号的默认行为。
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
signal(SIGINT, SIG_DFL);
while (1) {
printf("Default handling of SIGINT...\n");
sleep(1);
}
return 0;
}
阻塞信号
进程可以暂时阻塞某些信号,使其在解除阻塞之前不会被处理。使用sigprocmask
系统调用可以阻塞或解除阻塞信号。
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_BLOCK, &set, NULL);
printf("SIGINT is blocked. Try sending SIGINT...\n");
sleep(5);
sigprocmask(SIG_UNBLOCK, &set, NULL);
printf("SIGINT is unblocked.\n");
while (1) {
printf("Waiting for signal...\n");
sleep(1);
}
return 0;
}
信号队列
Linux支持实时信号,这些信号可以被排队处理。使用sigqueue
系统调用可以发送带有附加数据的信号。
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void handle_signal(int signum, siginfo_t *info, void *context) {
printf("Received signal %d with value %d\n", signum, info->si_value.sival_int);
}
int main() {
struct sigaction sa;
sa.sa_sigaction = handle_signal;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN, &sa, NULL);
union sigval value;
value.sival_int = 123;
sigqueue(getpid(), SIGRTMIN, value);
while (1) {
sleep(1);
}
return 0;
}
通过以上方式,Linux进程可以灵活地捕捉和处理信号,以适应不同的应用场景。