嵌入式Linux:发送实时信号
2026-10-043
非实时信号有一个明显的局限性:当同一个信号多次发生时,它只会被记录为一次,且不会记录发生的次数。因此,当该信号解除阻塞后,它只会被处理一次。这种行为使标准信号在某些应用场景中不够灵活。
相比之下,实时信号提供了几个关键优势:
- 信号范围扩大:标准信号通常使用 SIGUSR1 和 SIGUSR2,实时信号的编号范围更大(SIGRTMIN 到 SIGRTMAX,对应编号 34~64),可用于更多自定义目的。
- 队列化管理:同一个实时信号多次发生时,内核会记录每次事件并按顺序传递;标准信号通常只传递一次。
- 附带数据:实时信号可以携带整型数据或指针,接收方可以在处理函数中读取。
- 传递顺序保证:多个不同的实时信号处于等待状态时,编号越小的信号优先传递;同一个信号的多次传递保持发送顺序。
要使用实时信号,发送进程可以通过 sigqueue() 发送信号及附带数据,接收进程则需要通过 sigaction() 注册处理函数并启用 SA_SIGINFO。
sigqueue() 函数原型
sigqueue() 的函数原型如下:
#include <signal.h>
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 <stdio.h>
#include <stdlib.h>
#include <signal.h>
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 <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
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() 的附加值机制,适合进程间需要可靠传递事件及少量数据的场景。
来源:嵌入式Linux:发送实时信号(CSDN,原作者“不脱发的程序猿”,CC BY-SA 4.0)



