解决CreateProcess()的等待时间问题

简介: 一、引言:Windows下的API接口函数CreateProcess()可以用来创建一个进程和主线程。新进程执行指定的可执行文件(一般为.exe文件)。但如果要创建的进程是一个GUI界面的启动程序(类似QQ启动界面),启动该进程需要加载插件,并且只有该进程的服务完全启动后,后续才能调用相应接口实现功能。此时如何准确的等待进程启动起来,即等待子进程启动时间的界定是个难题。

二、Windows MSDN 中CreateProcess的使用方法:

STARTUPINFO si;

PROCESS_INFORMATION pi;

LPTSTR szCmdline=_tcsdup(TEXT("MyChildProcess"));

ZeroMemory( &si, sizeof(si) );

si.cb = sizeof(si);

ZeroMemory( &pi, sizeof(pi) );

// Start the child process.

if( !CreateProcess( NULL, // No module name (use command line)

 szCmdline, // Command line

 NULL, // Process handle not inheritable

 NULL, // Thread handle not inheritable

 FALSE, // Set handle inheritance to FALSE

 0, // No creation flags

 NULL, // Use parent's environment block

 NULL, // Use parent's starting directory

 &si, // Pointer to STARTUPINFO structure

 &pi ) // Pointer to PROCESS_INFORMATION structure

 )

{

 printf( "CreateProcess failed (%d)./n", GetLastError() );

 return;

}

// Wait until child process exits.

WaitForSingleObject( pi.hProcess, INFINITE );

// Close process and thread handles.

CloseHandle( pi.hProcess );

CloseHandle( pi.hThread );


      理论上讲,如果我创建的是Windows自带的程序如Nodepad.exe(记事本程序),此段代码首先通过CreateProcess()创建MyChildProcess=Nodepad.exe为子进程,子进程启动后父进程通过 WaitForSingleObject()函数等待其执行的结束,在子进程没有退出前父进程是一直处于阻塞状态的,这里子进程的作用同单线程中的函数类似。一旦子进程退出,WaitForSingleObject()函数所等待的pi.hProcess对象将得到通知,父进程将得以继续,如有必要可以通过GetExitCodeProcess()来获取子进程的退出代码。

三、疑问点:

      但是,正如引言描述,如果是我们单独启动的进程需要花费一定的时间,比如10s才能启动起来。上面的WaitForSingleObject()的第二个参数如果仍为 INFINITE无限等待的话是不妥当的,也就是说父进程是不知道创建的子进程花费多长时间启动起来的, 死等并不能从根本上解决问题。

四、解决方案:

      在子进程的启动代码标志性部分(如启动起来标志,程序退出标志)加上退出写 共享内存的代码,即将启动起来或中途退出用标记位标记写入共享内存。在创建子进程的下方轮询(间隔比如10ms一次)读取共享内存。

      1)如果得到启动的标志位,则退出轮询继续执行;

      2)如果得到中途退出的消息,则直接退出。这样就间接获取到了子进程的执行状态。

标记可以通过枚举类型设定,如下:

typedef  enum _PROCESS_STATE_STATUS

{

 PROCESS_STATE_OK,           //正常启动;

 PROCESS_STATE_TERMINIATE  //中途退出;

} PROCESS_STATE_STATUS;


共享内存作为进程通信的方式之一,正好解决了父进程如何获取子进程执行状态的问题。

五、个人反思:

       网络查询解决方案时,看到有人提出用:WaitForInputIdle解决。如下:调用进程可以通过WaitForInputIdle函数来等待新进程完成它的初始化并等待用户输入。这对于父进程和子进程之间的同步是极其有用的,因为CreateProcess函数不会等待新进程完成它的初始化工作。举例来说,在试图与新进程关联的窗口之前,进程应该先调用WaitForInputIdle。

      但是:我也曾经代码实验,WaitForInputIdle这个函数在CreateProcess之后只是为新进程 初始化进程代码然后就返回,并不是等进程完全创建好再返回。这一点大家可以用有界面的程序来测试,因为有界面的程序在代码初始化完成之后还要做一些其他事情然后再显示出界面的,所以创建有界面的程序显示界面的时候,WaitForInputIdle已经返回了。即: 对于GUI界面的启动程序WaitForInputIdle是不起作用的。


相关文章
|
JavaScript 前端开发 Python
CGI编程完全手册
一.基本原理 CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口。通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器端的CGI程序进行处理,最后返回结果给客户端。
3738 0
|
开发工具 数据安全/隐私保护 C++
[笔记] 编译bit7z踩坑记录
[笔记] 编译bit7z踩坑记录
1487 0
|
存储 XML JSON
【面试题精讲】Protobuf
【面试题精讲】Protobuf
|
机器学习/深度学习 人工智能 算法
现身说法,AI小白的大模型学习路径
写这篇文章的初衷:作为一个AI小白,把我自己学习大模型的学习路径还原出来,包括理解的逻辑、看到的比较好的学习材料,通过一篇文章给串起来,对大模型建立起一个相对体系化的认知,才能够在扑面而来的大模型时代,看出点门道。
1676 79
|
8月前
|
数据可视化 大数据 关系型数据库
基于python大数据技术的医疗数据分析与研究
在数字化时代,医疗数据呈爆炸式增长,涵盖患者信息、检查指标、生活方式等。大数据技术助力疾病预测、资源优化与智慧医疗发展,结合Python、MySQL与B/S架构,推动医疗系统高效实现。
|
算法 安全 数据安全/隐私保护
Crypto++库支持多种加密算法
【10月更文挑战第29天】Crypto++库支持多种加密算法
746 4
|
12月前
|
域名解析 网络协议 Linux
localhost 和 127.0.0.1 到底有啥区别?
`localhost` 和 `127.0.0.1` 是开发中常用的本地测试工具,它们虽常互换使用,但存在本质区别。本文深入解析两者定义、特点及差异:`localhost` 为域名,需解析为 IP(如 `127.0.0.1` 或 IPv6 的 `::1`),更灵活;`127.0.0.1` 是固定 IPv4 回环地址,解析更快。文章还探讨了特殊场景下的表现差异,并给出开发中的选择建议,助你更好地理解与应用。
1978 0
|
SQL 关系型数据库 Go
【Go语言专栏】Go语言中的数据库操作基础
【4月更文挑战第30天】本文介绍了Go语言中使用`database/sql`包与SQLite数据库交互的基础,包括导入包、建立连接、创建表、插入、查询、更新和删除数据。还涉及事务处理和错误处理,强调了错误检查的重要性。通过示例代码,展示了如何在Go中执行常见的数据库操作。更多学习资源可参考Go语言官方文档和SQLite官方文档。
515 0
|
C++
【qt】VS中如何配置Qt环境
【qt】VS中如何配置Qt环境
775 0
|
JSON 数据格式 C++
C++ JSON库 nlohmann::basic_json::accept的用法
C++ JSON库 nlohmann::basic_json::accept的用法
470 1