Linux:等待日渐唤醒的信号

1. 信号处理

在Linux系统中,信号是一种软件中断,用于通知进程发生了某个事件。进程可以捕捉并处理信号,也可以忽略信号,甚至可以将信号发送给其他进程。信号在日常的编程中经常用于中断正在执行的程序。

一个常见的例子是Ctrl+C组合键,它会向当前正在终端中运行的程序发送一个SIGINT信号。当程序收到这个信号时,可以捕捉它并执行一些特定的操作,例如安全退出或关闭文件。

在Linux系统中有许多不同类型的信号,每个信号有一个唯一的数字标识符,以及一个特定的名称。要使用信号,我们需要了解它们的标识符和名称。

2. 信号的状态

每个进程都有一个信号屏蔽字,用于指示当前屏蔽的信号。当一个信号被屏蔽时,系统不会将该信号传递给进程。我们可以使用sigprocmask函数来修改进程的信号屏蔽字。

2.1 信号的阻塞

当一个信号被阻塞时,它仍然会被记录,但不会被发送给进程。阻塞信号可以通过sigprocmask函数来设置。当信号被阻塞时,它会被添加到进程的信号屏蔽字中,以指示被阻塞的信号。

sigset_t mask;

sigemptyset(&mask);

sigaddset(&mask, SIGINT);

sigprocmask(SIG_BLOCK, &mask, NULL);

上述代码将阻塞了SIGINT信号。此时,如果程序收到SIGINT信号,它将不会被处理,直到解除信号的阻塞。

2.2 信号的解除阻塞

要解除对信号的阻塞,我们需要调用sigprocmask函数,并将信号从进程的信号屏蔽字中移除。

sigset_t mask;

sigemptyset(&mask);

sigaddset(&mask, SIGINT);

sigprocmask(SIG_UNBLOCK, &mask, NULL);

上述代码解除了对SIGINT信号的阻塞。

3. 等待信号

当我们希望程序在收到特定信号时暂停执行时,可以使用信号等待函数。Linux提供了几个函数来等待信号的到来。

3.1 pause函数

pause函数会使当前进程进入睡眠状态,直到捕捉到一个信号。当信号捕捉函数返回时,pause函数会返回-1,并且errno被设置为EINTR。下面是一个使用pause函数等待SIGINT信号的例子。

#include <stdio.h>

#include <signal.h>

void handler(int signum) {

// 处理SIGINT信号

printf("Received SIGINT signal!\n");

}

int main() {

signal(SIGINT, handler);

printf("Waiting for SIGINT signal...\n");

pause();

printf("Exiting...\n");

return 0;

}

当程序运行时,它会输出"Waiting for SIGINT signal...",然后进入等待状态。当按下Ctrl+C组合键发送SIGINT信号时,信号处理函数会被调用,并输出"Received SIGINT signal!"。程序将会继续执行,输出"Exiting..."。

3.2 sigwait函数

sigwait函数可以等待一个信号集中的信号,类似于条件变量的等待。下面是一个使用sigwait函数等待SIGINT信号的例子。

#include <stdio.h>

#include <signal.h>

int main() {

sigset_t set;

sigemptyset(&set);

sigaddset(&set, SIGINT);

int sig;

sigwait(&set, &sig);

printf("Received SIGINT signal!\n");

return 0;

}

当程序运行时,它会进入等待状态,直到收到SIGINT信号。sigwait函数会返回收到的信号,然后输出"Received SIGINT signal!"。程序将会继续执行。

3.3 sigsuspend函数

sigsuspend函数用于原子地解除进程的信号屏蔽字,并等待一个信号。它的用途与pause函数相似,但它可以自定义信号屏蔽字,而不仅仅是阻塞所有信号。

#include <stdio.h>

#include <signal.h>

void handler(int signum) {

// 处理SIGINT信号

printf("Received SIGINT signal!\n");

}

int main() {

signal(SIGINT, handler);

sigset_t mask;

sigemptyset(&mask);

sigaddset(&mask, SIGINT);

printf("Waiting for SIGINT signal...\n");

sigsuspend(&mask);

printf("Exiting...\n");

return 0;

}

当程序运行时,它会输出"Waiting for SIGINT signal...",然后进入等待状态。当按下Ctrl+C组合键发送SIGINT信号时,信号处理函数会被调用,并输出"Received SIGINT signal!"。程序将会继续执行,输出"Exiting..."。

总结

本文介绍了Linux系统中信号的处理和等待方法。信号是一种软件中断,用于通知进程发生了某个事件。我们可以通过阻塞和解除阻塞信号来控制信号的接收。信号等待函数可以让程序在收到特定信号时暂停执行。

在实际编程中,信号处理和等待是非常重要的技巧。它们可以用于实现进程之间的通信,或者在某些情况下优雅地终止程序。

操作系统标签