中断运行程序并保存数据



如何设计一个C/c++程序,使其在接收到中断信号后能够保存一些数据

我有一个长时间运行的程序,我可能需要在它结束运行之前杀死它(比如,按Ctrl-C)。当终止(而不是运行到结束)时,程序应该能够将一些变量保存到磁盘上。我有几本大的Linux书籍,但不太确定从哪里开始。一本食谱会很有帮助的。

谢谢。!

要做到这一点,你需要让你的程序观察一些东西,例如一个全局变量,它会告诉他停止它正在做的事情。

例如,假设长时间运行的程序执行一个循环,可以这样做:

g_shouldAbort = 0;
while(!finished)
{
   // (do some computing)
   if (g_shouldAbort)
   {
      // save variables and stuff
      break; // exit the loop
   }
}

将g_shouldport定义为全局volatile变量,如下所示:

static volatile int g_shouldAbort = 0;

(声明它为"volatile"是非常重要的,否则编译器看到没有人在循环中写它,可能会认为if (g_shouldport)总是为假并优化它)

然后,使用其他用户建议的例如信号 API,您可以这样做:
void signal_handler(int sig_code)
{
   if (sig_code == SIGUSR1) // user-defined signal 1
      g_shouldAbort = 1;
}

(当然,您需要注册这个处理程序,参见此处。

signal(SIGUSR, signal_handler);
然后,当你"发送"SIGUSR1信号给你的程序(例如用kill命令),g_shouldport将被设置为1,你的程序将停止它的计算。

希望有帮助!

注意:这种技术很简单,但很粗糙。当然,正如其他用户所描述的那样,使用信号和全局变量使得使用多个线程变得困难。

你想做的不是小事。您可以从使用signalsigaction为SIGINT (C-c)安装信号处理程序开始,但随后硬部分开始。

主要问题是,在信号处理程序中,你只能调用异步信号安全函数(或可重入函数)。大多数库函数不能可靠地认为是可重入的。例如,stdio函数,malloc, free和许多其他函数是不可重入的。

那么你怎么处理这个呢?在处理程序中设置flag(将某些全局变量done设置为1)并查找EINTR错误。在处理程序之外执行清理应该是安全的。

您正在尝试做的事情属于检查点/重新启动的范畴。

使用信号驱动的检查点/重启方案有几个大问题。一个是信号处理程序必须非常紧凑和原始。不能在信号处理程序中写入检查点。另一个问题是,当发送信号时,您的程序在执行状态的任何位置都可能是。几乎可以肯定的是,这个随机的位置并不是一个安全的点,不能让检查点从那里掉下来。然而,另一个问题是,您需要为您的程序配备一些应用程序端检查点/重新启动功能。

与其滚动自己的检查点/重启功能,我建议您考虑使用已经存在的免费功能。Linux上的GDB提供检查点/重启功能。另一种是DMTCP,参见http://dmtcp.sourceforge.net/index.html。

使用signal(2)sigaction(2)将函数指针分配给SIGINT信号,并在那里进行清理。

在保存函数中只输入一次

// somewhere in main
signal( SIGTERM, signalHandler );
signal( SIGINT,  signalHandler );
void saveMyData()
{
    // save some data here
}
void signalHandler( int signalNumber )
{
    static pthread_once_t semaphore = PTHREAD_ONCE_INIT;
    std::cout << "signal " << signalNumber << " received." << std::endl;
    pthread_once( & semaphore, saveMyData );
}

如果你的进程在你写完文件之前得到2个或更多的信号,你会保存奇怪的数据

最新更新