php 分叉问题

发布于 2024-10-17 22:53:30 字数 4383 浏览 1 评论 0原文

我有以下测试 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

十年不长 2024-10-24 22:53:31

只需使用 pcntl_wait() 即可。无需查看子进程是否完成,只需调用 pcntl_wait() 并阻塞直到子进程被收获。

避免传递 WNOHANG,以便您的父进程将坐下来等待子进程完成。

您可以将您编写的收获代码(从示例的第 58 行“$q=true;”开始)替换为:

$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);

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:

$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);
忆梦 2024-10-24 22:53:31

foreach 中的分叉:

<?
declare(ticks=1);
pcntl_signal(SIGUSR1, create_function('$signo', 'sleep(1);while (($pid=pcntl_wait(@$status, WNOHANG))>0) {}'));//protect against zombie children
foreach ($tasks as $v)
        {if (($pid=pcntl_fork())===-1)
            {//...
             continue;
            }
         else if ($pid===0)
              {ob_start();//prevent output to main process
               register_shutdown_function(create_function('$pars', 'ob_end_clean();posix_kill(posix_getppid(), SIGUSR1);posix_kill(getmypid(), SIGKILL);'), array());//to kill self before exit();, or else the resource shared with parent will be closed
               //...
               exit();//avoid foreach loop in child process
              }
        }
?>

Fork in foreach:

<?
declare(ticks=1);
pcntl_signal(SIGUSR1, create_function('$signo', 'sleep(1);while (($pid=pcntl_wait(@$status, WNOHANG))>0) {}'));//protect against zombie children
foreach ($tasks as $v)
        {if (($pid=pcntl_fork())===-1)
            {//...
             continue;
            }
         else if ($pid===0)
              {ob_start();//prevent output to main process
               register_shutdown_function(create_function('$pars', 'ob_end_clean();posix_kill(posix_getppid(), SIGUSR1);posix_kill(getmypid(), SIGKILL);'), array());//to kill self before exit();, or else the resource shared with parent will be closed
               //...
               exit();//avoid foreach loop in child process
              }
        }
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文