操作系统发送给进程的信号是中断,它们有能力提前结束一个程序。在 UNIX、LINUX、Mac OS X 或 Windows 系统上,按 Ctrl+C 会导致中断。被称为信号的中断会迫使操作系统暂停其当前任务,以便处理发送中断的任务。任何操作系统软件都可能因这些中断而服务暂停。同样,C++ 提供了各种可以被程序处理的信号。
信号处理函数只是一个与程序其余部分一起编译的函数。您可以使用 signal 或 sigaction 指示操作系统在收到信号时调用一个函数,而无需显式调用它。
C++ 用户可以处理以下众多信号及其操作列表。
| 信号 | 操作 |
|---|---|
|
SIGINT
|
创建已激活信号的收据 |
|
SIGTERM
|
发送终止程序的请求。 |
|
SIGBUS
|
总线错误指示了对错误地址的访问。 |
|
SIGILL |
查找了不允许的命令
|
|
SIGALRM
|
这作为计时器即将到期的提醒,并由 alarm() 函数使用。 |
|
SIGABRT |
意外发生的程序终止 |
|
SIGSTOP
|
该信号有能力停止一个进程,且无法被阻止、处理或忽略。 |
|
SIGSEGV
|
无效存储访问 |
|
SIGFPE
|
溢出或数学上不正确的操作,例如除以零。 |
|
SIGUSR1
|
这些是用户定义的信号 |
|
SIGSUR2
|
这些是用户定义的信号 |
C++ 信号处理包中的 signal() 函数可用于捕获意外的中断或事件。这意味着信号库的 signal() 函数可用,并用于捕获不需要的中断或事件。
语法
signal(registered signal, signal handler)
void (*signal (int sig, void (*func)(int)))(int);
这里的第一个参数是一个表示信号编号的整数,第二个参数是指向处理信号的函数的指针。我们需要记住,要捕获的信号需要使用 signal 函数进行注册,并连接到信号处理函数。信号处理函数需要是 void 类型。
#include <csignal>
#include <iostream>
using namespace std;
void signal_handler(int signal_num)
{
cout << "The interrupt signal is (" << signal_num
<< "). \n";
// It will terminates the program
exit(signal_num);
}
int main()
{
// register the signal SIGABRT as well as signal handler
signal(SIGABRT, signal_handler);
while (true)
cout << "Hai and Hello learnEtutorials..." << endl;
return 0;
}
输出
Hai and Hello learnEtutorials... Hai and Hello learnEtutorials... Hai and Hello learnEtutorials... Hai and Hello learnEtutorials...
输出:由于此代码处于无限循环中,因此它将显示上述输出,直到发生中断。
现在,如果我们使用 Ctrl+C 发送中断,程序将打印以下消息并结束。
输出
Hai and Hello learnEtutorials... Hai and Hello learnEtutorials... Hai and Hello learnEtutorials... Hai and Hello learnEtutorials... The interrupt signal is (22).
#include <iostream>
#include <csignal>
using namespace std;
sig_atomic_t signalled = 0;
void handler(int sig)
{
signalled = 1;
}
int main()
{
signal(SIGINT, handler);
raise(SIGINT);
if (signalled)
cout << "The Signal is handled";
else
cout << "The Signal is not handled";
return 0;
}
输出
The Signal is handled
要将信号发送到当前运行的应用程序,需要使用 C++ signal raise() 函数。raise() 函数在 <csignal> 头文件中指定,用于处理特定信号。
语法
int raise (int sig);
参数
sig:需要发送以进行处理的信号。它可以具有以下值
返回值
成功时返回零,失败时返回非零。
数据竞争
可以同时调用此函数而不会触发任何数据竞争。
异常
当引发信号且未分配处理函数来处理它时,此函数永远不会抛出异常。
示例 1
为了演示 raise() 函数在传递 SIGABRT 时如何使用,让我们看一个简单的例子
#include <iostream>
#include <csignal>
using namespace std;
sig_atomic_t sig_value = 0;
void handler(int sig)
{
sig_value = sig;
}
int main()
{
signal(SIGABRT, handler);
cout << "Before the signal handler is called" << endl;
cout << "Signal = " << sig_value << endl;
raise(SIGABRT);
cout << "After the signal handler is called" << endl;
cout << "Signal = " << sig_value << endl;
return 0;
}
输出
Before the signal handler is called Signal = 0 After the signal handler is called Signal = 6
示例 2
为了演示 raise() 函数在提供 SIGINT 时如何使用,让我们看一个简单的例子
#include <csignal>
#include <iostream>
using namespace std;
sig_atomic_t s_value = 0;
void handle(int signal_)
{
s_value = signal_;
}
int main()
{
signal(SIGINT, handle);
cout << "Before the called Signal = " << s_value << endl;
raise(SIGINT);
cout << "After the called Signal = " << s_value << endl;
return 0;
}
输出
Before the called Signal = 0 After the called Signal = 2
示例 3
作为如何使用 raise() 函数在提供 SIGTERM 时的方法,让我们看一个简单的例子
#include <csignal>
#include <iostream>
using namespace std;
sig_atomic_t s_value = 0;
void handle(int signal_)
{
s_value = signal_;
}
int main()
{
signal(SIGTERM, handle);
cout << "Before the called Signal = " << s_value << endl;
raise(SIGTERM);
cout << "After the called Signal = " << s_value << endl;
return 0;
}
输出
Before the called Signal = 0 After the called Signal = 15