C 库函数 - sigsuspend()
sigsuspend
函数是 C 标准库中的一个函数,用于临时替换当前的信号屏蔽字并挂起进程,直到捕捉到一个信号。它常用于实现原子信号等待,即在等待信号时不会丢失任何信号。
语法
int sigsuspend(const sigset_t *mask);
参数
const sigset_t *mask
:指向新的信号屏蔽字的指针。sigsuspend
使用该信号屏蔽字替换当前信号屏蔽字,并在捕捉到一个信号后恢复原来的信号屏蔽字。
返回值
sigsuspend
函数总是返回 -1,并将errno
设置为EINTR
,表示函数因信号中断。
实例
以下是一个使用 sigsuspend
函数等待特定信号的示例程序。该程序设置一个信号处理程序,然后使用 sigsuspend
挂起进程直到捕捉到信号。
实例
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t flag = 0;
// 自定义的信号处理函数
void handle_sigint(int sig) {
printf("Caught signal %d\n", sig);
flag = 1;
}
int main() {
struct sigaction sa;
sigset_t new_mask, old_mask, wait_mask;
// 设置 SIGINT 的处理程序为 handle_sigint
sa.sa_handler = handle_sigint;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// 初始化信号集
sigemptyset(&new_mask);
sigaddset(&new_mask, SIGINT);
// 阻塞 SIGINT 信号
if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) == -1) {
perror("sigprocmask");
return 1;
}
// 初始化等待信号集
sigemptyset(&wait_mask);
printf("Waiting for SIGINT...\n");
// 使用 sigsuspend 挂起进程,等待信号
while (!flag) {
if (sigsuspend(&wait_mask) != -1) {
perror("sigsuspend");
return 1;
}
}
// 恢复原来的信号屏蔽字
if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
perror("sigprocmask");
return 1;
}
printf("Exiting...\n");
return 0;
}
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t flag = 0;
// 自定义的信号处理函数
void handle_sigint(int sig) {
printf("Caught signal %d\n", sig);
flag = 1;
}
int main() {
struct sigaction sa;
sigset_t new_mask, old_mask, wait_mask;
// 设置 SIGINT 的处理程序为 handle_sigint
sa.sa_handler = handle_sigint;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGINT, &sa, NULL) == -1) {
perror("sigaction");
return 1;
}
// 初始化信号集
sigemptyset(&new_mask);
sigaddset(&new_mask, SIGINT);
// 阻塞 SIGINT 信号
if (sigprocmask(SIG_BLOCK, &new_mask, &old_mask) == -1) {
perror("sigprocmask");
return 1;
}
// 初始化等待信号集
sigemptyset(&wait_mask);
printf("Waiting for SIGINT...\n");
// 使用 sigsuspend 挂起进程,等待信号
while (!flag) {
if (sigsuspend(&wait_mask) != -1) {
perror("sigsuspend");
return 1;
}
}
// 恢复原来的信号屏蔽字
if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
perror("sigprocmask");
return 1;
}
printf("Exiting...\n");
return 0;
}
假设编译并运行程序后,输出将是:
Waiting for SIGINT...
当按下 Ctrl+C(发送 SIGINT
信号)时,输出将是:
Caught signal 2 Exiting...
程序捕捉到 SIGINT
信号,执行了信号处理函数 handle_sigint
,设置 flag
为 1,使得主循环终止并退出程序。
解释
sigset_t new_mask, old_mask, wait_mask;
:定义了三个信号集,用于控制信号屏蔽。- 使用
sigprocmask
函数阻塞SIGINT
信号,并保存原来的信号屏蔽字。 - 使用
sigsuspend
函数挂起进程,等待信号。sigsuspend
临时替换当前的信号屏蔽字为wait_mask
,并在捕捉到信号后恢复原来的信号屏蔽字。 - 在捕捉到信号后,恢复原来的信号屏蔽字,并继续执行程序。
注意事项
sigsuspend
常用于实现可靠的信号等待机制,避免信号在屏蔽期间丢失。- 信号处理函数应尽量简短,因为在处理信号时会阻塞其他信号。长时间运行的信号处理函数可能会影响程序的实时性。