我目前有一个我用 C 语言编写的程序,该程序有一个处理信息的无限循环,每个循环大约需要 5 分钟才能完成。我想在 shell 脚本中具有以下功能:
- 终止 C 程序
- 制作源码
- 运行程序
问题是,我不知道如何在不执行 ctrl+c 之类的操作的情况下告诉我的 C 程序退出,我宁愿它在终止自身之前完成当前正在处理的信息的处理。
告诉进程完成其业务并干净退出的 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
,并且使用相同的逻辑正常退出录制器。
像 ctrl+c 一样,我宁愿它在终止 itel 之前完成对当前正在处理的信息的处理
为 SIGINT 或您想要的任何东西建立一个信号处理程序,并在收到它后进行清理。但是,您不应该在处理程序本身中进行清理。
volatile sig_atomic_t do_cleanup = 0;
void handler(int sig)
{
do_cleanup = 1;
}
然后在你的主循环中,你只需要测试do_cleanup
并在你喜欢的时候退出。EINTR
如果您还没有这样做,您还必须小心正确处理错误。
以下是从 shell 发送信号的方法:
http://bash.cyberciti.biz/guide/Sending_signal_to_Processes
或者干脆man kill
以下是对信号的反应:
http://www.cs.cf.ac.uk/Dave/C/node24.html#SECTION002400000000000000000