悠悠楠杉
网站页面
正文:
在Linux系统中,信号(Signal)是进程间通信的重要方式之一,也是操作系统控制程序执行流程的关键机制。理解信号的本质及其处理方式,对于开发稳定可靠的系统程序至关重要。
信号本质上是模拟硬件中断的软件机制。当进程接收到信号时,会立即中断当前执行流程,转而处理信号。与硬件中断不同,信号的处理完全由内核调度,且具有以下特征:
- 异步触发:信号可能在任何时刻到达
- 不可靠性:相同信号在排队时可能被合并
- 多样性:Linux支持64种标准信号(1-64)
常见信号示例:
- SIGINT(2):Ctrl+C触发的终端中断信号
- SIGKILL(9):强制终止进程的不可捕获信号
- SIGSEGV(11):段错误信号
#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
// 示例:捕获SIGINT信号
void sig_handler(int signo) {
printf("Received signal %d\n", signo);
}
int main() {
signal(SIGINT, sig_handler);
while(1) pause();
}
提供更精细的控制能力:
struct sigaction {
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
};
// 示例:使用SA_RESTART自动重启被中断的系统调用
struct sigaction act;
act.sa_handler = sig_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
sigaction(SIGTERM, &act, NULL);
kill -15 1234
kill -9 1234
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
// 阻塞SIGINT信号
sigprocmask(SIG_BLOCK, &mask, NULL);
// 解除阻塞
sigprocmask(SIG_UNBLOCK, &mask, NULL);
void child_handler(int sig) {
int status;
pid_t pid = wait(&status);
printf("Child %d exited\n", pid);
}
int main() {
signal(SIGCHLD, child_handler);
if(fork() == 0) exit(0); // 子进程立即退出
sleep(1);
}
// 发送时需指定SA_SIGINFO标志
通过深入理解信号机制的本质特性,结合合理的函数调用和命令操作,开发者可以构建出健壮的Linux应用程序。信号虽是小巧的机制,却在系统稳定性、进程控制等方面发挥着不可替代的作用。