IPC通信之signal信号

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;
}
  1. 编译两个程序
    gcc one.c -o process_one
    gcc two.c -o process_two
    
  2. 运行接收者 (one)
    ./process_one
    
    记下它打印出来的 PID,比如 12345。
  3. 运行发送者 (two)(在另一个终端):
    • 发送暗号 1:./process_two 12345 1
    • 发送暗号 2:./process_two 12345 2

你会看到 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 个可用信号。

结果解读

  1. SIGUSR1 = 10, SIGUSR2 = 12:

    • 在你的系统上,这两个信号的编号是 10 和 12。
    • 这就是你仅有的两个“官方”自定义信号插槽。
    • 小贴士:不同架构(如 x86 vs ARM vs MIPS)这俩数字可能不一样,所以写代码时永远要用宏 SIGUSR1 而不是写死数字 10
  2. 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);
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容