您好,提前感谢您的关注。
在过去的两周里,我一直在与一些让我发疯的事情作斗争。我在我的 Windows 机器上安装了 APACHE (2.2.22) 和 PHP (5.4.3),我试图从同时调用另一个程序的 PHP 脚本中调用一个程序。这两个程序都是用 C/C++ 编写的,并用 MINGW32 编译。关于 Windows 版本,我测试了 Windows 2003 Server 和 Windows 7 Professional,都给我同样的问题。
让我介绍一下这两个程序:
1) mytask.exe:这是一个将在后台执行的程序,它会定期将其状态填充到文件中。
2)job.exe:这是我想从PHP脚本调用的程序。它的目标是将 mytask.exe 作为独立进程(而不是线程)生成。
如果我从控制台窗口运行下面的命令,那么 job.exe 会立即返回并让 mytask.exe 在后台运行,直到它终止。
> job.exe spawn mytask.exe
jobid=18874111458879FED
请注意,job.exe 会转储一个用于管理 mytask.exe 的标识符。例如:
> job.exe status 18874111458879FED
RUNNING
我已经检查过,如果我从 PHP 脚本运行第一个命令,PHP 脚本会永远随机阻塞。如果我查看 Windows 的任务管理器,我可以看到 job.exe 处于类似僵尸的状态。我可以断言 job.exereturn 0;
在其main()
例程中有效地达到了通常的语句,所以它似乎是在 C 运行时中的木头下的东西。此外,如果我编写一个简单的 mytask.exe,它只是休眠 10 秒,那么 PHP 脚本也会阻塞 10 秒(或者在我刚刚提到的随机行为之后永远阻塞)。换句话说,当我从 PHP 脚本调用 job.exe 时,我无法让 job.exe 生成一个进程而不等待它结束。
所以:在生成 mytask.exe 时我做错了,现在,这是题外话的第二部分。
我使用 WINAPI 函数CreateProcess()从 job.exe 生成任务。在 MSDN 文档中,我使用 调用 CreateProcess bInheritHandles = FALSE
,以避免子进程使用 PHP 脚本产生 I/O 死锁。我还关闭了 PROCESS_INFORMATION 结构中 CreateProcess() 返回的进程句柄。我唯一不做的就是等待过程结束。另一方面,关于 PHP 方面,我尝试了exec()
PHPproc_open()
函数来调用 job.exe,但没有成功。
不过,我最后的观察似乎是正确的,但它们并不能说服我,因为我不明白为什么它们会以某种方式起作用。事实上,如果 mytask.exefclose(stdout)
在睡眠之前执行,那么 PHP 脚本会立即返回。但是,如何???我告诉 CreateProcess() 不要继承句柄,那么为什么我会得到这些结果?无论如何,我不能坚持使用这个补丁,因为由 job.exe 启动的程序可能不知道是谁在调用它们,因此从这些程序中关闭 stdout 并不是一个好的解决方案。在 UNIX 中,事情就是这么简单......一个人只需调用fork()
,关闭标准流,然后调用execve
调用程序。在 Windows 中,我还尝试使用 CreateThread() 创建一个包装线程(以模拟 fork()),然后在关闭标准流后从该线程调用 CreateProcess() ......但这也关闭了 job.exe 的流!
所有这些问题都可以归结为一个问题:我如何从 PHP 中执行一个创建其他进程的程序?
我希望有人能对这个问题有所了解......非常感谢!