Web 界面提交 C 代碼 → 服務端編譯 → 運行可執行文件 → 返回結果。風險:用戶代碼死循環/死鎖導致進程無法返回,PHP exec()/popen() 同步阻塞,主進程無法超時控制,殭屍進程累積耗盡資源。
編寫獨立 process.exe 作為 PHP 的代理:
process.exe 而非直接啟動用戶程序process.exe 內部管理用戶程序生命周期、超時監控、強制終止process.exe 通過管道通信,設置 PHP 端超時兜底<?php
// filename: test1.php
$cmd = "test.exe 24 154"; // 用戶程序命令
$cmd = "process.exe 5000 " . $cmd; // 代理程序 + 超時毫秒數 + 用戶命令
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("file", "error-output.txt", "w+") // stderr
);
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
// 向子進程寫入輸入(如 scanf 所需)
fwrite($pipes[0], '12345678' . "\n");
fclose($pipes[0]);
// 讀取輸出
while (!feof($pipes[1])) {
echo nl2br(fgets($pipes[1], 1024));
}
fclose($pipes[1]);
// 關鍵:先關管道再關進程,避免死鎖
$return_value = proc_close($process);
echo "<br>command returned $return_value\n";
}
?>
argv[1] = 超時毫秒數,argv[2...] = 用戶命令CreateProcess / fork+exec)WaitForSingleObject(hProcess, timeout)TerminateProcess 強制殺死進程樹| 層級 | 機制 | 作用 |
|---|---|---|
| PHP 層 | proc_open + 管道 + proc_close | 異步啟動代理、流式讀取輸出、兜底超時 |
| 代理層 | process.exe 內部計時 + 強制終止 | 精確毫秒級超時控制、清理殭屍進程 |
| 用戶層 | 任意可執行文件 | 完全隔離,不影響主服務穩定 |
此模式將進程管理複雜度下沉到原生代碼層,PHP 僅作協調者,完美規避語言級限制。