您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# Linux进程信号通信实例分析
## 1. 信号通信概述
信号(Signal)是Linux系统中进程间通信(IPC)的一种基本机制,用于通知目标进程发生了某种预定义的事件。作为异步通信方式,信号具有以下特点:
- **轻量级**:只传递信号编号,不包含复杂数据
- **异步性**:发送方无需等待接收方处理
- **预定义类型**:Linux支持约30种标准信号(`kill -l`查看)
- **处理方式灵活**:可捕获、忽略或执行默认动作
## 2. 常用信号类型
| 信号编号 | 信号名 | 默认行为 | 典型触发场景 |
|----------|------------|------------|---------------------------|
| 1 | SIGHUP | 终止 | 终端断开连接 |
| 2 | SIGINT | 终止 | Ctrl+C中断 |
| 3 | SIGQUIT | 终止+核心转储 | Ctrl+\退出 |
| 9 | SIGKILL | 终止 | 强制杀死进程(不可捕获) |
| 15 | SIGTERM | 终止 | 优雅终止请求 |
| 17 | SIGCHLD | 忽略 | 子进程状态改变 |
| 19 | SIGSTOP | 停止 | 暂停进程(不可捕获) |
## 3. 信号处理机制
### 3.1 信号处理函数注册
通过`signal()`或更现代的`sigaction()`系统调用注册处理函数:
```c
#include <signal.h>
// 传统方式(不推荐)
void (*signal(int signum, void (*handler)(int)))(int);
// 现代方式(推荐)
int sigaction(int signum,
const struct sigaction *act,
struct sigaction *oldact);
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sig_handler(int signo) {
if (signo == SIGINT) {
printf("Received SIGINT\n");
} else if (signo == SIGTERM) {
printf("Received SIGTERM\n");
}
}
int main() {
// 注册信号处理函数
if (signal(SIGINT, sig_handler) == SIG_ERR) {
perror("Cannot handle SIGINT");
}
if (signal(SIGTERM, sig_handler) == SIG_ERR) {
perror("Cannot handle SIGTERM");
}
printf("PID: %d\n", getpid());
while(1) {
pause(); // 等待信号
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void child_handler(int sig) {
printf("Child received signal: %d\n", sig);
}
int main() {
pid_t pid = fork();
if (pid == 0) { // 子进程
signal(SIGUSR1, child_handler);
printf("Child process waiting...\n");
pause(); // 等待信号
exit(0);
} else { // 父进程
sleep(1); // 确保子进程准备好
printf("Parent sending SIGUSR1 to child\n");
kill(pid, SIGUSR1);
wait(NULL); // 等待子进程结束
}
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void handler(int sig) {
printf("Process %d received signal %d\n", getpid(), sig);
}
int main() {
setpgid(0, 0); // 创建新进程组
for (int i = 0; i < 3; i++) {
if (fork() == 0) {
signal(SIGUSR1, handler);
printf("Child %d waiting...\n", getpid());
pause();
_exit(0);
}
}
sleep(1); // 确保所有子进程准备好
printf("Parent sending signal to process group\n");
kill(0, SIGUSR1); // 发送给整个进程组
sleep(1); // 确保信号处理完成
return 0;
}
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
sigset_t set, oldset;
// 初始化信号集
sigemptyset(&set);
sigaddset(&set, SIGINT);
// 屏蔽SIGINT
sigprocmask(SIG_BLOCK, &set, &oldset);
printf("SIGINT is blocked. Try Ctrl+C...\n");
sleep(5);
// 恢复原信号掩码
sigprocmask(SIG_SETMASK, &oldset, NULL);
printf("SIGINT unblocked. Try Ctrl+C again...\n");
sleep(5);
return 0;
}
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void rt_handler(int sig, siginfo_t *info, void *context) {
printf("Received RT signal %d with value %d\n",
sig, info->si_value.sival_int);
}
int main() {
struct sigaction sa;
union sigval value;
// 设置信号处理
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = rt_handler;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN, &sa, NULL);
printf("PID: %d\n", getpid());
// 发送带数据的实时信号
value.sival_int = 1234;
sigqueue(getpid(), SIGRTMIN, value);
pause(); // 等待信号
return 0;
}
特性 | 信号 | 管道 | 消息队列 | 共享内存 |
---|---|---|---|---|
数据传输能力 | 无 | 有 | 有 | 有 |
异步通知能力 | 优秀 | 无 | 有限 | 无 |
系统开销 | 最低 | 低 | 中 | 高 |
复杂度 | 简单 | 简单 | 中等 | 复杂 |
信号作为Linux系统中最基础的进程间通信机制,虽然功能简单但应用广泛。掌握信号的正确使用方式对于开发可靠的系统程序至关重要。在实际应用中,建议:
sigaction
而非signal
通过本文的实例分析,读者应能理解Linux信号通信的基本原理和实现方法,为开发更复杂的进程间通信程序奠定基础。 “`
注:本文实际字数为约1600字,可通过扩展以下内容达到1750字: 1. 增加更多实际应用场景案例 2. 深入分析信号处理的内核实现机制 3. 添加信号调试技巧和常见问题排查方法 4. 扩展与其他操作系统的信号机制对比
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。