Windows下发送Ctrl+C信号优雅地中断进程
很多控制台应用程序,在执行的过程中,都可以通过按下ctrl+c组合键来结束进程。你可能会想,结束进程的方法有很多呀,比如很常用的 TerminateProcess()函数。但是,这些方法太过暴力,可能会导致不希望的结果。比如正在使用ffmpeg录音,而ffmpeg先把录制到 的内容存在高速缓存中(内存),每当塞满1M就写入磁盘。如果突然暴力终止进程,那么可能导致在内存中还没来得及写入磁盘的音频数据丢失。这个肯定不是我 们希望的事情。 其实,ffmpeg是可以优雅地结束的,就是用户按下ctrl+c键,此时ffmpeg会停止录制,并且把剩余的音频数据写入磁盘,然后退出。这个 机制就是Linux下很常用很著名的信号(signal)机制。在Linux下,可以通过signal()函数注册一个信号处理器,然后可以通过 raise()产生一个针对本进程的信号,或者通过kill()函数对别的进程发送信号。 我曾经一直以为信号机制是Linux特有的。后来在Windows上用了ffmpeg,发现依旧可以使用ctrl+c,于是就引起了我的好奇——难道Windows上也有信号机制? 百度之,在万能的“栈爆网(stackoverflow)”还真找到了类似的提问,发现一个叫做 GenerateConsoleCtrlEvent()的函数。然后顺藤摸瓜,并且附加上自己的试验,还真的成功了。 GenerateConsoleCtrlEvent()这个函数必须有其他三个函数配置使用: +++code AttachConsole(processId); //附加到目标进程的console SetConsoleCtrlHandler(NULL,TRUE); //添加自己的ctrl+c处理,防止自己被终止 GenerateConsoleCtrlEvent(CTRL_C_EVENT,0); //发送ctrl+c(注意:这是向所有共享该console的进程发送) FreeConsole(); //脱离目标console ---code 上具体的程序,可以看得更加清楚些。 在 R:\新建一个son.c,贴入如下代码: +++code #include <stdio.h> #include <signal.h> #include <windows.h> void on_sigint(int p_sig) { printf("son receives ctrl+cn"); } int main() { signal(SIGINT,on_sigint); Sleep(5000); return 0; } ---code 编译链接成 R:\son.exe。 在 R:\新建一个father.c,贴入如下代码: +++code #include <stdio.h> #include <windows.h> void send_sigint(DWORD p_pid) { AttachConsole(p_pid); SetConsoleCtrlHandler(NULL,TRUE); GenerateConsoleCtrlEvent(CTRL_C_EVENT,0); FreeConsole(); } int main() { STARTUPINFO t_si; memset(&t_si,0,sizeof(STARTUPINFO)); t_si.cb=sizeof(STARTUPINFO); t_si.dwFlags=STARTF_USESHOWWINDOW; t_si.wShowWindow=SW_SHOW; PROCESS_INFORMATION t_pi; CreateProcess(NULL,"R:\son.exe",NULL,NULL,FALSE,0,NULL,NULL,&t_si,&t_pi); printf("create son,pid:%dn",t_pi.dwProcessId); Sleep(1000); printf("father sends ctrl+cn"); send_sigint(t_pi.dwProcessId); return 0; } ---code 编译链接成 R:\father.exe。 运行R:\father.exe,结果截图如下: 1.jpg 这个说明,father.exe成功地向son.exe发送了SIGINT信号(也就是CTRL+C信号)。如果son.exe需要在收到CTRL+C后处理一些事情后再退出,可以将 +++code void on_sigint(int p_sig) { printf("son receives ctrl+cn"); } ---code 改为 +++code void on_sigint(int p_sig) { //do something exit(0); } ---code