php 分叉问题
我有以下测试 php 来执行 fork/spawn 过程,其中测试还尝试在完成后杀死子进程(僵尸)。
我希望有一个更有效的过程,其中任何子进程都会立即删除尽快从进程表中删除。当前尝试填满了进程表,并导致内存分配问题,导致系统关闭。该应用程序在 Fedora/Centos 系统上运行。
当它运行时,我遇到了内存分配错误,并且在被删除之前生成了太多进程。
任何指示将不胜感激,谢谢..
$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";
}
更新::: 设法得到我认为的解决方案......
//--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;
}
}
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..
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.
Any pointers would be greatly appreciated on this thanks..
$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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
只需使用 pcntl_wait() 即可。无需查看子进程是否完成,只需调用 pcntl_wait() 并阻塞直到子进程被收获。
避免传递 WNOHANG,以便您的父进程将坐下来等待子进程完成。
您可以将您编写的收获代码(从示例的第 58 行“$q=true;”开始)替换为:
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.
Avoid passing WNOHANG so that your parent process will sit and wait for a child to finish.
You can replace the reaping code you've written (starting at line 58 '$q=true;' of your example) with this:
foreach 中的分叉:
Fork in foreach: