我能阻止用户在后台运行我的C++程序吗?
在C++编程中,有一个问题是如何阻止用户在后台运行程序。但是,这样做是不好的做法。UNIX的约定是假设用户是正确操作的,因此应该相应地进行调整。要么修改程序,使其能够作为后台进程干净地运行,要么假设用户会将输出导向到像/dev/null
或日志文件中的东西。
以下是一种解决方法,可以修改程序使其在后台运行。修改的代码示例如下:
#include#include int main() { pid_t pid = fork(); if (pid < 0) { std::cerr << "Fork failed." << std::endl; return 1; } if (pid > 0) { // Parent process return 0; } // Child process // Your program logic goes here return 0; }
上述代码使用了`fork()`函数来创建一个子进程。如果`fork()`返回的值小于0,则表示创建子进程失败。如果返回的值大于0,则表示当前进程是父进程,可以直接退出。如果返回的值等于0,则表示当前进程是子进程,可以在其中编写程序逻辑。
另一种解决方法是假设用户会将程序的输出导向到/dev/null
或日志文件中。这样可以确保程序在后台运行时不会产生任何输出。以下是示例代码:
#includeint main() { // Your program logic goes here // Redirect output to /dev/null or a log file freopen("/dev/null", "w", stdout); freopen("/dev/null", "w", stderr); return 0; }
以上代码使用了`freopen()`函数将标准输出和标准错误输出重定向到/dev/null
文件,这样程序在后台运行时就不会在终端上产生任何输出。你也可以将输出重定向到其他日志文件中。
总之,要么修改程序使其能够干净地作为后台进程运行,要么假设用户会将输出导向到/dev/null
或日志文件中,以防止用户在后台运行程序时产生不必要的输出。
可以通过以下方法防止用户在后台运行C++程序:
#define _POSIX_SOURCE #include#include #include // fileno #include // isatty #include // signal #include // fcntl #include // tcgetattr/tcsetattr void handle_input(int /*sig*/) { signal(SIGTTIN, SIG_IGN); std::cin.setstate(std::ios::failbit); } void handle_output(int /*sig*/) { signal(SIGTTOU, SIG_IGN); std::cout.setstate(std::ios::failbit); } class TCAttr { int m_fd; termios m_attr; public: TCAttr(int fd) : m_fd(fd), m_attr() { if(tcgetattr(m_fd, &m_attr) != 0) m_fd = -1; } TCAttr(FILE* fp) : TCAttr(fileno(fp)) {} TCAttr() : m_fd(-1), m_attr() {} ~TCAttr() { if(m_fd>=0) tcsetattr(m_fd, TCSADRAIN, &m_attr); } bool set_lmode(tcflag_t flag) { termios tmp; if(tcgetattr(m_fd, &tmp)!=0) return false; tmp.c_lflag = flag; return tcsetattr(m_fd, TCSADRAIN, &tmp)==0; } bool add_lmode(tcflag_t flag) { termios tmp; if(tcgetattr(m_fd, &tmp)!=0) return false; tmp.c_lflag |= flag; return tcsetattr(m_fd, TCSADRAIN, &tmp)==0; } bool remove_lmode(tcflag_t flag) { termios tmp; if(tcgetattr(m_fd, &tmp)!=0) return false; tmp.c_lflag &= ~flag; return tcsetattr(m_fd, TCSADRAIN, &tmp)==0; } }; int main() { TCAttr tca(stdout); if(isatty(fileno(stdin))) { signal(SIGTTIN, handle_input); } if(isatty(fileno(stdout))) { signal(SIGTTOU, handle_output); tca.add_lmode(TOSTOP); } std::cout << "Thanks for not streaming to a tty in background mode\n"; std::string name; std::cin >> name; std::cout << name << "\n"; }
以上代码会阻止程序在后台运行时输出到标准输出(std::cout
),但仍然可以将输出重定向到文件或管道中。程序运行时,如果在后台模式下请求终端输入,会触发SIGTTIN信号,通过信号处理函数handle_input
将std::cin
设置为失败状态。同样地,如果在后台模式下请求终端输出,会触发SIGTTOU信号,通过信号处理函数handle_output
将std::cout
设置为失败状态,并且还会使用tca.add_lmode(TOSTOP)
函数将输入模式设置为TOSTOP。最后,程序会打印一条消息,然后从终端输入一个字符串,将其输出到终端。