嵌入式Linux:发送实时信号

2026-10-20 10:06:58 9阅读

非实时信号有一个明显的局限性:当同一个信号多次发生时,它只会被记录为一次,且不会记录发生的次数。因此,当该信号解除阻塞后,它只会被处理一次。这种行为使标准信号在某些应用场景中不够灵活。

相比之下,实时信号提供了几个关键优势:

  • 信号范围扩大:标准信号通常使用 SIGUSR1 和 SIGUSR2,实时信号的编号范围更大(SIGRTMIN 到 SIGRTMAX,对应编号 34~64),可用于更多自定义目的。
  • 队列化管理:同一个实时信号多次发生时,内核会记录每次事件并按顺序传递;标准信号通常只传递一次。
  • 附带数据:实时信号可以携带整型数据或指针,接收方可以在处理函数中读取。
  • 传递顺序保证:多个不同的实时信号处于等待状态时,编号越小的信号优先传递;同一个信号的多次传递保持发送顺序。

要使用实时信号,发送进程可以通过 sigqueue() 发送信号及附带数据,接收进程则需要通过 sigaction() 注册处理函数并启用 SA_SIGINFO。

sigqueue() 函数原型

sigqueue() 的函数原型如下:

#include 
int sigqueue(pid_t pid, int sig, const union sigval value);

参数说明:

  • pid:接收信号的进程 ID。
  • sig:要发送的信号编号,也可以设置为 0 来检查进程是否存在。
  • value:union sigval 类型的值,可以携带整型数据或指针。

成功时返回 0;失败时返回 -1,并设置 errno。

union sigval 定义如下:

typedef union sigval {
    int sival_int;   // 整型数据
    void *sival_ptr; // 指针数据
} sigval_t;

1、发送进程

发送进程使用 sigqueue() 向另一个进程发送实时信号及其伴随数据。下面的示例从命令行读取目标进程 ID 和信号编号,并附带一个整型值:

#include 
#include
#include

int main(int argc, char *argv[]) {
union sigval sig_val;
int pid, sig;

// 检查参数个数
if (argc < 3) {
exit(-1);
}

// 获取命令行参数
pid = atoi(argv[1]);
sig = atoi(argv[2]);

printf("Sending signal %d to process %d", sig, pid);

// 发送信号,并附带整型数据
sig_val.sival_int = 10;
if (sigqueue(pid, sig, sig_val) == -1) {
perror("sigqueue error");
exit(-1);
}

puts("Signal sent successfully!");
return 0;
}

2、接收进程

接收进程使用 sigaction() 绑定实时信号处理函数,并从 siginfo_t 中读取附带数据:

#include 
#include
#include
#include

static void sig_handler(int sig, siginfo_t *info, void *context) {
(void)context;
sigval_t sig_val = info->si_value;

printf("Received real-time signal: %d", sig);
printf("Attached data: %d", sig_val.sival_int);
}

int main(int argc, char *argv[]) {
struct sigaction sa = {0};
int sig;

if (argc < 2) {
exit(-1);
}

// 获取命令行传递的信号编号
sig = atoi(argv[1]);

// 绑定信号处理函数
sa.sa_sigaction = sig_handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);

if (sigaction(sig, &sa, NULL) == -1) {
perror("sigaction error");
exit(-1);
}

// 等待信号
while (1) {
sleep(1);
}

return 0;
}

标准信号适用于多数常见场景,但无法记录同一信号的多次发生,也不能携带附加数据。实时信号通过队列化传递和 sigqueue() 的附加值机制,适合进程间需要可靠传递事件及少量数据的场景。


作者:不脱发的程序猿
链接:https://www.aiddithome.com/p/27eb3011b0256.html
本作遵循 [CC BY 4.0 署名] 许可,版权归作者所有。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
5条评论
装过才知道
1楼 · 1天前

goood,国产Linux实战教程就该这么写

触底反弹的Tony
2楼 · 1天前

sigqueue带参数发信号比传统kill强太多,还能带上整型数据

实时信号处理函数里拿siginfo带的数据,这个写法实用

双向进程一收一发,整个demo很完整,照着跑通了

原来实时信号还能排队,跟普通信号的区别一下明白了