1

我目前有一个我用 C 语言编写的程序,该程序有一个处理信息的无限循环,每个循环大约需要 5 分钟才能完成。我想在 shell 脚本中具有以下功能:

  • 终止 C 程序
  • 制作源码
  • 运行程序

问题是,我不知道如何在不执行 ctrl+c 之类的操作的情况下告诉我的 C 程序退出,我宁愿它在终止自身之前完成当前正在处理的信息的处理。

4

3 回答 3

4

告诉进程完成其业务并干净退出的 POSIX 标准方法是向其发送SIGTERM信号。根据您的应用程序,退出 on 可能合适,也可能不合适SIGINT,这意味着中断进程,而不是终止进程。(Control-c 发送SIGINT。)

尝试在你的紧密循环中放置一个标志;在容易退出的时候检查标志,但仍然足够频繁以迅速退出。在您的情况下,收到 aSIGTERM可能会立即在系统日志上显示一条消息,然后承诺在接下来的 5 分钟内退出。

您的信号处理程序将如下所示:

static int signalled;  // if nonzero, what signal have we been sent?

static void SignalHandler(int signum) {
  signalled = signum;
}

我在每次 I/O 操作后检查全局static变量signalled,这意味着每秒多次。

这是我捕获和恢复信号的代码:

static __sighandler_t sh, si, st;

static void catch_signals(void) {
  if ((sh = signal(SIGHUP, SignalHandler)) == SIG_IGN) signal(SIGHUP, SIG_IGN);
  if ((si = signal(SIGINT, SignalHandler)) == SIG_IGN) signal(SIGINT, SIG_IGN);
  if ((st = signal(SIGTERM, SignalHandler)) == SIG_IGN) signal(SIGTERM, SIG_IGN);
  signalled = 0;
}

static void restore_signals(void) {
  signal(SIGHUP, sh);
  signal(SIGINT, si);
  signal(SIGTERM, st);
}

(这段代码来自一个图书馆,所以我要格外小心地按照我找到它们的方式保留它们。)

额外技巧:当时间到期(这是一个电视录制库)时,定时器刚刚设置signalled = SIGTERM,并且使用相同的逻辑正常退出录制器。

于 2012-08-11T14:03:34.767 回答
3

像 ctrl+c 一样,我宁愿它在终止 itel 之前完成对当前正在处理的信息的处理

为 SIGINT 或您想要的任何东西建立一个信号处理程序,并在收到它后进行清理。但是,您不应该在处理程序本身中进行清理。

volatile sig_atomic_t do_cleanup = 0;
void handler(int sig)
{
    do_cleanup = 1;
}

然后在你的主循环中,你只需要测试do_cleanup并在你喜欢的时候退出。EINTR如果您还没有这样做,您还必须小心正确处理错误。

于 2012-08-11T13:55:06.233 回答
1

以下是从 shell 发送信号的方法:

http://bash.cyberciti.biz/guide/Sending_signal_to_Processes

或者干脆man kill

以下是对信号的反应:

http://www.cs.cf.ac.uk/Dave/C/node24.html#SECTION002400000000000000000

于 2012-08-11T14:04:40.993 回答