每种信号的含义
在Linux操作系统中,信号是一种进程间通信的方式,用于通知进程发生了某种事件。Linux中的普通信号(standard signals)有31个,每个信号都有特定的用途。以下是这31个普通信号的列表及其描述:
- SIGHUP (1): 挂起信号,通常在终端断开或关闭时发送给控制进程。
- SIGINT (2): 中断信号,通常由用户按下
Ctrl+C
键发送。 - SIGQUIT (3): 退出信号,通常由用户按下
Ctrl+\
键发送并生成核心转储。 - SIGILL (4): 非法指令,程序执行了非法或未定义的机器语言指令。
- SIGTRAP (5): 跟踪/断点陷阱,用于调试。
- SIGABRT (6): 异常终止,由
abort()
函数调用发送。 - SIGBUS (7): 总线错误,内存访问对齐错误。
- SIGFPE (8): 浮点异常,如除零或溢出。
- SIGKILL (9): 强制终止信号,不能被捕获或忽略,立即终止进程。
- SIGUSR1 (10): 用户定义信号1,应用程序可以自定义使用。
- SIGSEGV (11): 段错误,非法内存访问。
- SIGUSR2 (12): 用户定义信号2,应用程序可以自定义使用。
- SIGPIPE (13): 管道破裂,写入一个没有读取端的管道。
- SIGALRM (14): 闹钟信号,由
alarm()
函数设置的定时器到期时发送。 - SIGTERM (15): 终止信号,程序可以捕获该信号并执行清理操作。
- SIGSTKFLT (16): 协处理器堆栈错误(较少使用)。
- SIGCHLD (17): 子进程状态改变,当子进程终止或停止时发送给父进程。
- SIGCONT (18): 继续执行,如果进程已停止则恢复其执行。
- SIGSTOP (19): 停止执行,不能被捕获或忽略。
- SIGTSTP (20): 终端停止信号,通常由用户按下
Ctrl+Z
键发送。 - SIGTTIN (21): 后台进程尝试从终端读取时发送。
- SIGTTOU (22): 后台进程尝试向终端写入时发送。
- SIGURG (23): 紧急条件,套接字上有紧急数据可读。
- SIGXCPU (24): CPU时间限制超时。
- SIGXFSZ (25): 文件大小限制超时。
- SIGVTALRM (26): 虚拟定时器到期。
- SIGPROF (27): 统计定时器到期。
- SIGWINCH (28): 终端窗口大小改变。
- SIGPOLL (29): I/O操作事件(SysV定义)。
- SIGPWR (30): 电源故障。
- SIGSYS (31): 非法系统调用。
这些信号在编程和系统管理中有着重要的应用。通过使用信号,进程可以处理各种异常和特殊情况,实现更健壮和灵活的程序设计。
捕获SIGINT信号
SIGINT信号通常由用户按下Ctrl+C
键发送。以下代码展示了如何捕获和处理SIGINT信号:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
// 信号处理函数
void handle_sigint(int sig) {
printf("Caught signal %d (SIGINT)\n", sig);
}
int main() {
// 注册信号处理函数
signal(SIGINT, handle_sigint);
// 无限循环,等待信号
while (1) {
printf("Running...\n");
sleep(1);
}
return 0;
}
编译并运行该程序后,当你按下Ctrl+C
时,它将捕获SIGINT信号并调用handle_sigint
函数。
捕获SIGTERM信号
SIGTERM信号通常用于请求进程终止。以下代码展示了如何捕获和处理SIGTERM信号:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
// 信号处理函数
void handle_sigterm(int sig) {
printf("Caught signal %d (SIGTERM)\n", sig);
// 进行清理工作
printf("Cleaning up...\n");
// 终止程序
_exit(0);
}
int main() {
// 注册信号处理函数
signal(SIGTERM, handle_sigterm);
// 无限循环,等待信号
while (1) {
printf("Running...\n");
sleep(1);
}
return 0;
}
编译并运行该程序后,可以通过以下命令发送SIGTERM信号:
kill -SIGTERM <pid>
其中,<pid>
是程序的进程ID。
捕获SIGCHLD信号
SIGCHLD信号在子进程终止或停止时发送给父进程。以下代码展示了如何捕获和处理SIGCHLD信号:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
// 信号处理函数
void handle_sigchld(int sig) {
// 等待子进程终止
wait(NULL);
printf("Caught signal %d (SIGCHLD). Child process terminated.\n", sig);
}
int main() {
// 注册信号处理函数
signal(SIGCHLD, handle_sigchld);
// 创建子进程
pid_t pid = fork();
if (pid == 0) {
// 子进程代码
printf("Child process running...\n");
sleep(2);
printf("Child process exiting...\n");
_exit(0);
} else {
// 父进程代码
printf("Parent process waiting for child to terminate...\n");
// 无限循环,等待信号
while (1) {
sleep(1);
}
}
return 0;
}
编译并运行该程序后,子进程将在2秒后终止,父进程将捕获SIGCHLD信号并调用handle_sigchld
函数。
两种不能被忽略的信号
SIGKILL和SIGSTOP
两种不能被捕捉的信号
SIGKILL和SIGSTOP