信号处理

277 阅读2分钟

信号处理

信号是由操作系统传递到进程的中断,它可以提前终止一个程序。在 UNIX,LINUX,Mac OS X 或 Windows 系统上,你可以通过按 Ctrl+C 产生一个中断。

有的信号不能被程序捕获到,但是下面列出的信号,你可以在程序中捕捉它们,并且可以基于这些信号进行相应的操作。这些信号定义在 C++ 头文件 <csignal> 中。

  • SIGABRT
    • 程序的异常终止,例如调用 abort。
  • SIGFPE
    • 一个错误的算术运算,例如除以零或运算结果溢出。
  • SIGILL
    • 检测到非法指令。
  • SIGINT
    • 接收到交互注意信号。
  • SIGSEGV
    • 一个非法的存储访问。
  • SIGTERM
    • 发送给程序的终止请求信号。

signal() 函数

C++ 信号处理库提供 signal 函数来捕获意外事件。以下是 signal() 函数的语法:

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

简单来说,这个函数接收两个参数:第一个参数是一个整数,表示信号号码;第二个参数是一个指向信号处理函数的指针。

让我们用 signal() 函数写一个简单的 C++ 程序,用它来捕捉 SIGINT 信号。不管你想在程序中捕获什么信号,你必须使用 signal 函数注册该信号,并将其与信号处理程序相关联。 例子如下所示:

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler(int signum) {
  cout << "Interrupt signal (" << signum << ") received.\n";

  // cleanup and close up stuff here
  // terminate program

  exit(signum);
}

int main() {
  // register signal SIGINT and signal handler
  signal(SIGINT, signalHandler);

  while(1) {
    cout << "Going to sleep...." << endl;
    sleep(1);
  }

  return 0;
}

当上述代码编译和执行后,将会产生以下的结果:

Going to sleep....
Going to sleep....
Going to sleep....

现在,按 Ctrl+C 来中断这个程序,你会看到程序将捕获的信号,并会通过打印展示出来,如下所示:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

raise() 函数

您可以通过 raise() 函数生成信号,它用一个整数的信号编号作为参数,语法如下所示。

int raise (signal sig);

这里的 sig 是要发送的信号编号,这些信号是:SIGINT,SIGABRT,SIGFPE,SIGILL,SIGSEGV,SIGTERM,SIGHUP。以下是我们使用 raise() 函数从程序内部发出一个信号的例子:

#include <iostream>
#include <csignal>

using namespace std;

void signalHandler(int signum) {
  cout << "Interrupt signal (" << signum << ") received.\n";

  // cleanup and close up stuff here
  // terminate program

   exit(signum);
}

int main() {
  int i = 0;
  // register signal SIGINT and signal handler
  signal(SIGINT, signalHandler);

  while(++i) {
    cout << "Going to sleep...." << endl;
    if(i == 3) {
      raise(SIGINT);
    }
    sleep(1);
  }

  return 0;
}

当上述代码编译和执行后,将会产生以下的结果,并且这些结果会自动出现:

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.