在开始之前,我想澄清一下,这不是一个命令行工具,而是一个通过它自己的命令行界面接受命令的应用程序。
编辑:我必须为之前的解释道歉,显然我没有做好解释它的工作。再来一次......
我正在构建一个接受用户命令的命令行界面应用程序。我有一个信号处理程序设置来捕获信号,然后设置我需要终止应用程序的标志。我遇到的问题是我能找到的所有控制台功能都是阻塞的,这意味着我无法检测到我需要退出控制台处理循环,直到用户按下某个键(或输入,具体取决于函数) )。
是否有一些标准的方法我可以做非块控制台交互,或者是否有一种优雅的方式来构建程序,这样如果我只是从信号线程终止,那么一切都将被正确处理和释放(请不要我不明白这一点,我知道如何使用锁定和释放信令线程中的资源来实现这一点,但这可能会变得混乱,所以我宁愿避免使用它。)
希望这种解释更有意义......
答案 0 :(得分:8)
好的 - 这适用于Windows和Windows是便携式的 - 请注意#ifdef SIGBREAK - 这不是标准信号。
#include <csignal>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
namespace
{
volatile sig_atomic_t quit;
void signal_handler(int sig)
{
signal(sig, signal_handler);
quit = 1;
}
}
int main()
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#ifdef SIGBREAK
signal(SIGBREAK, signal_handler);
#endif
/* etc */
while (!quit)
{
string s;
cin >> s;
cout << s << endl;
}
cout << "quit = " << quit << endl;
}
答案 1 :(得分:6)
在* nix上,您可以使用signal
函数注册信号处理程序:
#include <signal.h>
void signal_handler(int sig)
{
// Handle the signal
}
int main(void)
{
// Register the signal handler for the SIGINT signal (Ctrl+C)
signal(SIGINT, signal_handler);
...
}
现在,只要有人按Ctrl + C,就会调用你的信号处理程序。
答案 2 :(得分:2)
在Windows中:SetConsoleCtrlHandler
答案 3 :(得分:1)
在基于* nix的系统上,您可能不需要信号处理程序来实现此功能。您可以指定要忽略SIGINT调用
int main(void)
{
// Register to ignore the SIGINT signal (Ctrl+C)
signal(SIGINT, SIG_IGN);
while(1)
{
retval = my_blocking_io_func();
if(retval == -1 && errno == EINTR)
{
// do whatever you want to do in case of interrupt
}
}
}
这种方法的重要方法是识别非阻塞函数是否会被中断。通常,您会意识到阻塞功能失败(例如read())并重新尝试该功能。如果是其他值,您将采取相应的错误相关操作。
答案 4 :(得分:0)
线程安全的更好的* nix解决方案是使用pthread_sigmask()而不是signal() 例如,这是您在当前线程和未来生成的线程中签署SIGINT,SIGTERM和SIGPIPE的方式:
sigset_t waitset;
sigemptyset(&waitset);
sigaddset(&waitset, SIGINT);
sigaddset(&waitset, SIGTERM);
sigaddset(&waitset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &waitset, NULL);