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系统中信号的处理和等待方法。信号是一种软件中断,用于通知进程发生了某个事件。我们可以通过阻塞和解除阻塞信号来控制信号的接收。信号等待函数可以让程序在收到特定信号时暂停执行。
在实际编程中,信号处理和等待是非常重要的技巧。它们可以用于实现进程之间的通信,或者在某些情况下优雅地终止程序。