one.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handle_msg(int sig) {
if (sig == SIGUSR1) {
printf("\n[ONE] 收到信号 SIGUSR1 -> 暗号含义:今晚行动!\n");
} else if (sig == SIGUSR2) {
printf("\n[ONE] 收到信号 SIGUSR2 -> 暗号含义:任务取消,撤退!\n");
}
}
int main() {
// 注册信号处理函数
signal(SIGUSR1, handle_msg);
signal(SIGUSR2, handle_msg);
printf("=== 接收者 ONE (PID: %d) ===\n", getpid());
printf("我正在等待来自 TWO 的暗号 (SIGUSR1 或 SIGUSR2)...\n");
while(1) {
pause(); // 挂起进程,直到收到信号
}
return 0;
}
two.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("使用方法: %s <目标PID> <暗号类型 1或2>\n", argv[0]);
return 1;
}
int target_pid = atoi(argv[1]);
int type = atoi(argv[2]);
printf("=== 发送者 TWO ===\n");
printf("目标 PID: %d\n", target_pid);
if (type == 1) {
printf("正在发送暗号 1 (SIGUSR1)...\n");
kill(target_pid, SIGUSR1); // 发送信号
} else if (type == 2) {
printf("正在发送暗号 2 (SIGUSR2)...\n");
kill(target_pid, SIGUSR2);
} else {
printf("未知暗号类型!\n");
}
return 0;
}
-
编译两个程序:
gcc one.c -o process_one gcc two.c -o process_two -
运行接收者 (one):
记下它打印出来的 PID,比如 12345。./process_one -
运行发送者 (two)(在另一个终端):
- 发送暗号 1:
./process_two 12345 1 - 发送暗号 2:
./process_two 12345 2
- 发送暗号 1:
你会看到 process_one 立即做出反应,打印出对应的消息。这就是基于 Signal 的 IPC。虽然不能传图片、文字,但传个简单的指令(1 或 2)是绰绰有余的。
查询可用信号
main.c
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main() {
printf("=== 信号数量探查 ===\n");
// 1. SIGUSR 家族
// 标准只定义了这两个
printf("SIGUSR1 = %d\n", SIGUSR1);
printf("SIGUSR2 = %d\n", SIGUSR2);
printf(">> SIGUSR 系列只有 2 个。\n\n");
// 2. Real-time 家族
// SIGRTMIN 和 SIGRTMAX 是运行时确定的宏或函数调用
int rt_min = SIGRTMIN;
int rt_max = SIGRTMAX;
printf("SIGRTMIN (实时信号起始) = %d\n", rt_min);
printf("SIGRTMAX (实时信号结束) = %d\n", rt_max);
printf(">> Real-time 系列共有 %d 个可用信号。\n", rt_max - rt_min + 1);
return 0;
}
运行结果:
=== 信号数量探查 ===
SIGUSR1 = 10
SIGUSR2 = 12
>> SIGUSR 系列只有 2 个。
SIGRTMIN (实时信号起始) = 34
SIGRTMAX (实时信号结束) = 64
>> Real-time 系列共有 31 个可用信号。
结果解读
-
SIGUSR1 = 10, SIGUSR2 = 12:
- 在你的系统上,这两个信号的编号是 10 和 12。
- 这就是你仅有的两个“官方”自定义信号插槽。
- 小贴士:不同架构(如 x86 vs ARM vs MIPS)这俩数字可能不一样,所以写代码时永远要用宏
SIGUSR1而不是写死数字10。
-
SIGRTMIN = 34, SIGRTMAX = 64:
- 从 34 到 64,整整 31 个空闲频段等你使用。
- 如果你的程序需要很复杂的控制逻辑(比如:指令1=启动引擎,指令2=开启日志,指令3=切换数据库...),完全可以用这 31 个信号来实现。
如何使用这 31 个信号?
非常简单,就像数组下标一样:
// 发送信号
kill(pid, SIGRTMIN + 0); // 自定义指令 0
kill(pid, SIGRTMIN + 1); // 自定义指令 1
...
kill(pid, SIGRTMIN + 10); // 自定义指令 10
// 接收信号
signal(SIGRTMIN + 0, my_handler_0);
signal(SIGRTMIN + 1, my_handler_1);