我目前有一个用C语言编写的程序,它有一个处理信息的无限循环,每个循环大约需要5分钟才能完成。我想在shell脚本中具有以下功能:
问题是,我不知道如何告诉我的C程序退出而不执行ctrl + c这样的操作,我宁愿它在终止自身之前完成处理它当前正在处理的信息。
答案 0 :(得分:4)
告诉流程完成业务并彻底退出的POSIX标准方法是向其发送SIGTERM
信号。根据您的应用程序,它可能或不适合退出SIGINT
,这意味着中断进程,而不是终止进程。 (Control-c发送SIGINT
。)
尝试在紧密的循环中放置一个标志;在退出很容易的时候检查标志,但仍然经常足以立即退出。在您的情况下,收到SIGTERM
可能会立即在系统日志中显示一条消息,然后承诺在接下来的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
,并使用相同的逻辑正常退出录像机。
答案 1 :(得分:3)
像ctrl + c一样,我宁愿它完成处理它的信息 目前正在努力终止itsel
为SIGINT或任何你想要的东西建立一个信号处理程序,并在收到它后进行清理。 不应该在处理程序本身进行清理。
volatile sig_atomic_t do_cleanup = 0;
void handler(int sig)
{
do_cleanup = 1;
}
然后在您的主循环中,您只需要测试do_cleanup
并在您需要时退出。如果您还没有这样做,还必须小心处理EINTR
错误。
答案 2 :(得分:1)
以下是如何从shell发送信号:
http://bash.cyberciti.biz/guide/Sending_signal_to_Processes
或只是man kill
以下是对信号的反应:
http://www.cs.cf.ac.uk/Dave/C/node24.html#SECTION002400000000000000000