问题描述
我有以下测试php来执行fork/spawn进程,该测试还尝试在完成后杀死子进程(僵尸)..
I have the following test php to do a fork/spawn process, where the test also attempts to kill the child process (zombie) after is completes..
我想拥有一个更高效的流程,在该流程中,所有子流程都应尽快从流程表中立即删除.当前尝试填满了进程表,并导致内存分配问题,从而关闭了系统.该应用程序在Fedora/Centos系统上运行.
I'd like to have a more efficient process, where any child processes are immediately removed from the process table as soon as possible. The current attempt fills up the process table, and causes a memory allocation issue that shuts down the system. The app is running on a Fedora/Centos system.
运行此程序时,我遇到了内存分配错误,并且在删除它们之前产生了太多的进程.
I'm running into a memory allocation err when this runs, and there are too many processes that get spawned, before they get removed.
感谢任何指针.
$fname="ef_deptData.txt";
$t=0;
$pids = array();
$pids1[] = array();
$fh=fopen($fname,"r");
$p=0;
while(!feof($fh))
{
print " inside course pppppppppppppppppppppp \n";
//--go ahead and parse the line of input from the file
//--(if it exists)
$buf = fgets($fh);
$buf=trim($buf);
if($buf)
{
$data1=explode("&&",$buf);
$stateVal=trim($data1[0]);
$collegeVal=trim($data1[1]);
$campusVal=trim($data1[2]);
$pid = pcntl_fork();
//process the spawned child procs
if($pid)
{
$pids[$p]=$pid;
$p=$p+1;
}
else
{
$app="ef_course.py";
$args[0]='"'.$stateVal.'"';
$args[1]='"'.$collegeVal.'"';
$args[2]='"'.$campusVal.'"';
pcntl_exec($app, $args);
}
}
$t=$t+1;
if($t==40)
{
sleep(5);
$t=0;
}
}
// --this section is a kludge to see if the child process is complete
// --prior to deleting the spwaned child process (should be a better way)
$q=true;
while($q)
{
$a="ps -aux | grep ef_course | grep -v grep | awk '{print $8}'";
$a=`$a`;
$t=explode("\n",$a);
$t=array_slice($t,1,-1);
print_r($t);
sleep(5);
$y=0;
for($i=0;$i<count($t);$i++)
{
if((strcmp($t[$i],"Z+")!=0)&&(strcmp($t[$i],"Z")!=0))
{
$y=1;
print "ddd \n";
}
}
if($y==0)
{
//--try to go ahead and kill the zombie processes
$w="pgrep ef_course";
$r=`$w`;
if($r!="")
{
//foreach($pids as $p){ posix_kill($p,SIGHUP); }
//foreach($pids as $p){ posix_kill($p,SIGINT); }
foreach($pids as $p){ posix_kill($p,SIGTERM); }
$dead_and_gone = pcntl_waitpid(-1,$status,WNOHANG);
while($dead_and_gone > 0){
// Remove the gone pid from the array
unset($pids[array_search($dead_and_gone,$pids)]);
// Look for another one
$dead_and_gone = pcntl_waitpid(-1,$status,WNOHANG);
}
print_r($pids);
}
else
$q=false;
}
sleep(10);
print "waiting for ef_course.py to complete \n";
}
更新:::设法得到了我认为的解决方案.....
update:::managed to get what i think is a solution.....
//--start the process to get the store urls..
$fname="ef_programData.txt";
$t=0;
$pids = array();
$pids1[] = array();
$fh=fopen($fname,"r");
$p=0;
while(!feof($fh))
{
print " inside program pppppppppppppppppppppp \n";
//--go ahead and parse the line of input from the file
//--(if it exists)
$tmp=array();
$buf = fgets($fh);
$buf=trim($buf);
if($buf)
{
$data1=explode("&&",$buf);
$pid = pcntl_fork();
//process the spawned child procs
if($pid)
{
$pids[]=$pid;
}
else
{
$args=array();
$app="foo.py";
$args[0]='"'.$stateVal.'"';
pcntl_exec($app, $args);
}
while(pcntl_wait($status, WNOHANG) > 0) {
usleep(500);
}
while(list($key, $val) = each($pids)) {
if(!posix_kill($val, 0)) { // This detects if the child is still running or not
unset($pids[$key]);
}
}
$pids = array_values($pids); // Reindex the array
}
$t=$t+1;
if($t==40)
{
sleep(5);
$t=0;
}
}
推荐答案
只需使用pcntl_wait().无需查看子进程是否已完成,只需调用pcntl_wait()并阻塞直到获得子进程即可.
Just use pcntl_wait(). There's no need to see if the child process has finished, just call pcntl_wait() and block until the child is reaped.
避免传递WNOHANG,这样您的父进程将坐下来等待孩子完成.
Avoid passing WNOHANG so that your parent process will sit and wait for a child to finish.
您可以使用以下代码替换您编写的收割代码(从示例的第58行'$ q = true;'开始):
You can replace the reaping code you've written (starting at line 58 '$q=true;' of your example) with this:
$status = null;
do {
// You can use $status with pcntl_wifexited(), pcntl_wifstopped(),
// pcntl_wifsignaled(), pcntl_wexitstatus(), pcntl_wtermsig() and
// pcntl_wstopsig() if you need to.
$pid = pcntl_wait($status);
} while ($pid > 0);
这篇关于PHP的分叉问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!