gpt4 book ai didi

c++ - 子进程 C++ 的 Windows 控制台信号处理

转载 作者:行者123 更新时间:2023-11-28 04:25:52 32 4
gpt4 key购买 nike

假设我们有一个用 C++ 编写的小程序,如下所示。
该程序本身有意不通过 WinAPI 调用 SetConsoleCtrlHandler 执行信号处理 - 这是问题的重要部分。

#include <stdio.h>
#include <stdlib.h>

int main() {
while(true) {
int status = system("EXTERNAL COMMAND");
printf("RESULT STATUS = %d\n", status);
}
}

当在终端中按下 Ctrl+C 组合键时,上面的程序会有完全不同的行为,这取决于调用了哪个 "EXTERNAL COMMAND"

1) 如果外部命令是pause,程序会进入死循环,一步步调用pause命令,打印"RESULT STATUS = 0 "多次,但未通过进程终止强制终止。
2) 如果在选择中有外部命令,程序将在Ctrl+C按下后立即终止。它不会打印任何内容,也不会从 system 调用返回。
3) 如果外部命令是set/P VAR=,程序会有很多有趣的行为。当按下 Ctrl+C 时,程序打印 `"RESULT STATUS = 1"并继续工作直到执行第一次异步调用。

第一种和第二种情况可以用以下方式解释。终端窗口位于用户输入和目标程序之间,因此当用户按下 Ctrl+C 时,终端窗口会自行向目标进程发送信号。
因此,一些子进程可以通过 hConsole = GetStdHandle(STD_OUTPUT_HANDLE) 手动获取终端处理程序并执行自己的信号处理。另一个子进程不这样做,所以信号传递给父进程并终止它。

但是第三种情况引起了很大的问题。如果子进程拦截 SIGINT,为什么父进程在第一次异步调用后执行终止。如果不是,为什么它不立即终止,为什么以及如何打印 `"RESULT STATUS = 1"并继续工作。

谢谢

最佳答案

Windows 中没有 Unix 信号,至少不是来自内核。也就是说,Windows 和 Windows API 基本上是基于 C 编程语言的,而 C 编程语言是与 Unix 一起开发的,确实需要 six signals。 . Windows 中的 C 运行时模拟 SIGABRTSIGTERM在进程内(例如与 C raise 一起使用)。对于 SIGSEGV , SIGILL , 和 SIGFPE它使用操作系统异常处理程序。在控制台应用程序中,标准 SIGINT及非标SIGBREAK与 C 运行时的控制台控制处理程序关联,通常是通过 SetConsoleCtrlHandler 注册的第一个处理程序. CTRL_C_EVENT映射到 SIGINT信号处理程序和所有其他( CTRL_BREAK_EVENTCTRL_CLOSE_EVENT )映射到 SIGBREAK处理程序。

控制台控制事件由控制台主机 (conhost.exe) 发送,它通过让 session 服务器 (csrss.exe) 在客户端进程中创建一个线程来实现。此线程从未记录的 CtrlRoutine 开始kernelbase.dll 中的函数,它遍历已注册的控制处理程序,直到其中一个通过返回 true 来处理事件。如果它们都不处理该事件,则默认处理程序调用 ExitProcess(STATUS_CONTROL_C_EXIT) .注意 SetConsoleCtrlHandler(NULL, TRUE)设置一个标志,使 CtrlRoutine忽略 CTRL_C_EVENT ,并且此标志由子进程继承,并在创建带有标志 CREATE_NEW_PROCESS_GROUP 的进程时默认启用.此外,对于 CTRL_CLOSE_EVENT , session 服务器给每个进程 5 秒的时间来处理事件并自行退出,否则它会强制终止进程。

了解 CMD 的内部发生了什么 PAUSE命令,参见 SetConsoleMode ,特别是 ENABLE_PROCESSED_INPUT . PAUSE调用 C _getch ,它暂时将控制台输入模式设置为 0。在禁用处理输入模式的情况下,Ctrl+C 被简单地读作“\x03”,而不是生成 CTRL_C_EVENT。 .

关于c++ - 子进程 C++ 的 Windows 控制台信号处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54362699/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com