我们来深入学习 rt_sigpending 系统调用,摘要:rt_sigpending系统调用用于检查被阻塞但尚未处理的待处理信号集。通过sigpending函数调用,可获取当前被屏蔽信号的”等待中”状态,类似查看”信号邮箱”中的未读邮件。使用时需配合sigprocmask设置信号屏蔽字,并结合sigset_t相关函数操作信号集。示例代码演示了如何阻塞SIGUSR1/SIGUSR2信号,在10秒内捕获待处理信号,最后解除阻塞使信号被处理。该机制适用于需要延迟处理特定信号的场景。(149字)
1. 函数介绍
在 Linux 中,你可以使用 sigprocmask 来阻塞(或屏蔽)某些信号,这意味着即使这些信号被发送到你的进程,它们也不会立即被处理,而是进入一种“等待中”(pending)的状态。
data-ad-format="fluid"
data-ad-layout-key="-7k+ex-4a-9w+4a">
rt_sigpending(通常通过用户空间的 sigpending 函数调用)的作用就是让你检查当前有哪些信号正处于这种“等待中”的状态。这在你需要知道在屏蔽信号期间发生了哪些信号时非常有用。
你可以把它想象成一个“信号邮箱”的查看器:当信号被阻塞时,它们就像邮件一样被“投递”到你的邮箱里(变成 pending),但你暂时不“阅读”它们。sigpending 就是让你打开邮箱看看里面有哪些“未读邮件”(待处理信号)。
2. 函数原型
1 2 3 4
| #include <signal.h>
int sigpending(sigset_t *set);
|
3. 功能
获取当前进程中所有被阻塞且已产生但尚未递送(即待处理)的信号集合。
4. 参数
set:
5. 返回值
6. 相似函数或关联函数
sigprocmask: 用于设置或查询当前进程的信号屏蔽字(signal mask),即哪些信号当前被阻塞。
sigset_t: 用于存储信号集合的数据类型。
sigemptyset: 初始化一个 sigset_t 集合为空。
sigfillset: 初始化一个 sigset_t 集合,使其包含所有信号。
sigaddset: 向一个 sigset_t 集合中添加一个特定的信号。
sigdelset: 从一个 sigset_t 集合中删除一个特定的信号。
sigismember: 检查一个特定的信号是否属于某个 sigset_t 集合。
7. 示例代码
下面是一个例子,演示如何阻塞信号,然后使用 sigpending 来检查哪些信号在等待。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| #define _GNU_SOURCE // 启用 GNU 扩展 #include <stdio.h> #include <stdlib.h> // 包含 exit #include <unistd.h> // 包含 sleep #include <signal.h> // 包含信号处理相关函数 #include <string.h> // 包含 memset
// 一个简单的信号处理函数 void signal_handler(int sig) { printf("Caught signal %d\n", sig); // 在实际应用中,信号处理函数应尽量简短,并只调用异步信号安全函数 }
int main() { sigset_t block_set; // 用于设置要阻塞的信号 sigset_t pending_set; // 用于接收待处理的信号集
printf("My PID is: %d\n", getpid());
// 1. 设置 SIGUSR1 和 SIGUSR2 的处理函数 struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; // 使用上面定义的处理函数 sigemptyset(&sa.sa_mask); // 处理函数执行时不额外阻塞信号 sa.sa_flags = 0; // 没有特殊标志
if (sigaction(SIGUSR1, &sa, NULL) == -1) { // 设置 SIGUSR1 的处理 perror("sigaction SIGUSR1"); exit(EXIT_FAILURE); } if (sigaction(SIGUSR2, &sa, NULL) == -1) { // 设置 SIGUSR2 的处理 perror("sigaction SIGUSR2"); exit(EXIT_FAILURE); }
// 2. 创建一个信号集,并添加要阻塞的信号 (SIGUSR1 和 SIGUSR2) sigemptyset(&block_set); // 初始化为空集 sigaddset(&block_set, SIGUSR1); // 添加 SIGUSR1 sigaddset(&block_set, SIGUSR2); // 添加 SIGUSR2
// 3. 使用 sigprocmask 阻塞 SIGUSR1 和 SIGUSR2 printf("Blocking SIGUSR1 and SIGUSR2...\n"); printf("Try sending them now:\n"); printf(" In another terminal, run: 'kill -USR1 %d'\n", getpid()); printf(" In another terminal, run: 'kill -USR2 %d'\n", getpid()); printf("Sleeping for 10 seconds...\n");
if (sigprocmask(SIG_BLOCK, &block_set, NULL) == -1) { perror("sigprocmask BLOCK"); exit(EXIT_FAILURE); }
// 4. 在阻塞期间睡眠,等待信号发送 sleep(10); printf("10 seconds passed. Signals should be pending now.\n");
// 5. 调用 sigpending 检查哪些信号在等待 if (sigpending(&pending_set) == -1) { perror("sigpending"); exit(EXIT_FAILURE); }
// 6. 检查并打印待处理的信号 printf("Checking pending signals:\n"); if (sigismember(&pending_set, SIGUSR1)) { printf(" SIGUSR1 is pending.\n"); } else { printf(" SIGUSR1 is NOT pending.\n"); }
if (sigismember(&pending_set, SIGUSR2)) { printf(" SIGUSR2 is pending.\n"); } else { printf(" SIGUSR2 is NOT pending.\n"); }
// 7. 解除对 SIGUSR1 和 SIGUSR2 的阻塞 printf("Unblocking SIGUSR1 and SIGUSR2...\n"); if (sigprocmask(SIG_UNBLOCK, &block_set, NULL) == -1) { perror("sigprocmask UNBLOCK"); exit(EXIT_FAILURE); }
printf("Unblocked. Any pending signals should be delivered now.\n"); printf("Sleeping for 1 second to allow signal handlers to run...\n"); sleep(1);
printf("Program exiting.\n"); return 0; }
|
编译和运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # 假设代码保存在 sigpending_example.c 中 gcc -o sigpending_example sigpending_example.c
# 终端 1: 运行程序 ./sigpending_example # 程序会输出 PID,例如 My PID is: 12345 # 然后提示你发送信号
# 终端 2: 发送信号 (在程序提示的 10 秒内执行) kill -USR1 12345 kill -USR2 12345
# 观察终端 1 的输出,你会看到程序报告哪些信号是 pending 的, # 以及在解除阻塞后信号被处理。
|
这个例子清晰地展示了信号阻塞和 sigpending 的工作流程:信号被阻塞 -> 信号发送 -> 信号变为 pending -> 使用 sigpending 查询 -> 解除阻塞 -> pending 的信号被处理。
https://www.calcguide.tech/2025/08/24/rt-sigpending系统调用及示例/
rt_sigpending系统调用及示例-CSDN博客