C++ 信号处理基础教程文档

收录于 2023-04-20 00:10:05 · بالعربية · English · Español · हिंदीName · 日本語 · Русский язык · 中文繁體

信号是由操作系统传递给进程的中断,以停止正在进行的任务并参加为其生成中断的任务。 信号也可以由操作系统根据系统或错误情况生成。 您可以通过在 C 来生成中断.lidihuo.com/linux-tutorial"> Linux ,UNIX,Mac OS X或Windows系统。
有些信号不能被程序捕获,但是下面列出了一些信号,您可以在程序中捕获它们,并可以根据信号采取适当的措施。
这些信号在<csingnal>头文件中定义。
以下是信号列表以及它们的描述和工作能力:
信号 说明
SIGABRT (信号中止)程序异常终止,例如调用中止。
SIGFPE (信号浮点异常)错误的算术运算,例如被零除或导致溢出的运算。
SIGILL (信号非法指令),用于检测非法指令。
SIGINT (信号中断),用于接收交互式程序中断信号。
SIGSEGV (违反信号分割)对存储的无效访问。
SIGTERM (信号终止)发送到程序的终止请求。
SIGHUP (信号挂断)挂断(POSIX),它报告用户终端断开连接。用于报告控制过程的终止。
SIGQUIT 用于终止进程并生成核心转储。
SIGTRAP 跟踪陷阱。
SIGBUS 这是BUS错误,表明访问了无效地址。
SIGUSR1 用户定义的信号1、
SIGUSR2 用户定义的信号2、
SIGALRM 闹钟,指示访问无效地址。
SIGTERM 用于终止。该信号可以被阻止,处理和忽略。由kill命令生成。
SIGCOUNT 此信号发送到进程以使其继续。
SIGSTOP 停止,不可阻挡。该信号用于停止进程。无法处理,忽略或阻止此信号。

signal()函数

C++ signal-处理库提供函数信号以捕获意外中断或事件。

语法

void (*signal (int sig, void (*func)(int)))(int);

参数

此功能设置为处理信号。
它指定一种处理由 指定的信号编号的方法。 sig 。
参数 func 指定程序可以处理信号的三种方式之一。
默认处理(SIG_DFL): 由该特定信号的默认操作处理的信号。 忽略信号(SIG_IGN): 即使无意,该信号也将被忽略并且代码将继续执行。 函数处理程序: 定义了一个特定的函数来处理信号。
我们必须记住,我们要捕获的信号必须使用信号功能进行注册,并且必须与信号处理功能相关联。
注意: 信号处理功能应为void类型。

返回值

此函数的返回类型与参数func的类型相同。
如果成功请求此函数后,该函数将返回指向特定处理程序函数的指针,该函数负责在调用之前处理此信号。

数据争用

数据竞赛未定义。如果在多线程程序中调用此函数,则会导致未定义的行为。

异常

此函数绝不会引发异常。

示例1

让我们看一个简单的示例来演示signal()函数的使用:
#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 << "Signal is handled";
    else
        cout << "Signal is not handled";
    return 0;
}
输出:
Signal is handled

示例2

让我们看另一个简单的示例:
#include <csignal>
#include <iostream>
 
namespace
{
  volatile std::sig_atomic_t gSignalStatus;
}
 
void signal_handler(int signal)
{
  gSignalStatus = signal;
}
 
int main()
{
  // Install a signal handler
  std::signal(SIGINT, signal_handler);
 
  std::cout << "SignalValue: " << gSignalStatus << '\n';
  std::cout << "Sending signal " << SIGint << '\n';
  std::raise(SIGINT);
  std::cout << "SignalValue: " << gSignalStatus << '\n';
}
输出:
SignalValue: 0
Sending signal 2
SignalValue: 2

raise()函数

C++信号raise()函数用于将信号发送到当前正在执行的程序。
<csignal> 头文件声明了函数handle()以处理特定信号。

语法

int raise (int sig);

参数

信号: 要发送以进行处理的信号号。它可以采用以下值之一:
SIGINT SIGABRT SIGFPE SIGILL SIGSEGV SIGTERM SIGHUP

返回值

成功则返回0,失败则返回非零。

数据争用

同时调用此函数是安全的,不会引起数据争用。

异常

如果未使用信号定义函数处理程序来处理引发的信号,则此函数永远不会引发异常。

示例1

让我们看一个简单的示例来说明在传递SIGABRT时使用raise()函数:
#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 signal handler is called" << endl;
    cout << "Signal = " << sig_value << endl; 
    raise(SIGABRT);
    cout << "After signal handler is called" << endl;
    cout << "Signal = " << sig_value << endl;
    return 0;
}
输出:
Before signal handler is called
Signal = 0
After signal handler is called
Signal = 6

示例2

让我们看一个简单的示例,以说明在传递SIGINT时对raise()函数的使用:
#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 called Signal = " << s_value << endl; 
    raise(SIGINT); 
    cout << "After called Signal = " << s_value << endl; 
    return 0; 
}
输出:
Before called Signal = 0
After called Signal = 2

示例3

让我们看一个简单的示例,以说明在传递SIGTERM时对raise()函数的使用:
#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 called Signal = " << s_value << endl; 
    raise(SIGTERM); 
    cout << "After called Signal = " << s_value << endl; 
    return 0; 
}
输出:
Before called Signal = 0
After called Signal = 15

示例4

让我们看一个简单的示例,以说明在传递SIGSEGV时对raise()函数的使用:
#include <csignal> 
#include <iostream> 
using namespace std; 
  
sig_atomic_t s_value = 0; 
void handle(int signal_) 
{ 
    s_value = signal_; 
} 
  
int main() 
{ 
    signal(SIGSEGV, handle); 
    cout << "Before called Signal = " << s_value << endl; 
    raise(SIGSEGV); 
    cout << "After called Signal = " << s_value << endl; 
    return 0; 
}
输出:
Before called Signal = 0
After called Signal = 11

示例5

让我们看一个简单的示例来说明在传递SIGFPE时使用raise()函数:
#include <csignal> 
#include <iostream> 
using namespace std; 
  
sig_atomic_t s_value = 0; 
void handle(int signal_) 
{ 
    s_value = signal_; 
} 
  
int main() 
{ 
    signal(SIGFPE, handle); 
    cout << "Before called Signal = " << s_value << endl; 
    raise(SIGFPE); 
    cout << "After called Signal = " << s_value << endl; 
    return 0; 
}
输出:
Before called Signal = 0
After called Signal = 8