2012-04-16 2 views
1

나는 우분투 리눅스 머신에서 실행중인 PHP 스크립트를 가지고있다. 이 스크립트는 pcntl_fork() 함수를 사용하여 여러 프로세스를 생성하고 pcntl_waitpid() 함수를 사용하여 해당 함수가 종료되었음을 기록합니다. 이 VERY (종종 약 40-50/초라고 추정 됨), 을 생성하지만이 프로세스는 각각 즉시 (나는 exit()posix_kill(${pid}, SIGKILL)을 사용해 보았습니다. 스크립트는 수 초 동안 잘 동작하지만 (10 초에서 30 초 정도), 필연적으로 '자식'프로세스 생성이 중단되고 중지됩니다. 스크립트로 인한 컴퓨터의 메모리 사용량은 증가하지 않지만 Ctrl-C로 스크립트를 강제 종료 할 때까지 스크립트가 중단되면 컴퓨터의 CPU가 천천히 증가합니다. 각 프로세스는 한 줄의 텍스트를 구문 분석하고 마지막으로 파일에 저장합니다. 테스트 목적으로, 나는 자식 프로세스를 생성하자마자 바로 종료한다. 한 테스트에서 1400 개의 프로세스가 성공적으로 시작되고 스크립트가 중단되기 전에 종료되었습니다.PHP에서 전역 프로세스 생성 제한은 무엇입니까?

나는 기계가 ulimit을 가지고 있다는 것을 알고 있지만, 프로세스의 수를 제한한다고 읽었다 고 나는 믿는다. 이 스크립트는 생성되는 즉시 하위 프로세스를 종료하므로 어떤 일이 일어나고 있는지 혼란 스럽습니다.

 
core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
scheduling priority    (-e) 0 
file size    (blocks, -f) unlimited 
pending signals     (-i) 29470 
max locked memory  (kbytes, -l) 64 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 1024 
pipe size   (512 bytes, -p) 8 
POSIX message queues  (bytes, -q) 819200 
real-time priority    (-r) 0 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 29470 
virtual memory   (kbytes, -v) unlimited 
file locks      (-x) unlimited 

스크립트를 실행하는 동안 생성 프로세스의 총 수를 결정 PHP 글로벌 한계가있다 : 여기 내 현재 ulimit를 구성 (ulimit -a)의 출력은? **이 자식 프로세스는 즉시 종료되므로이 문제는 시스템 리소스를 도용하는 프로세스를 무제한으로 만드는 문제는 아니라고 생각합니다. 나는이

 
$this->process_control->fork(array($this, "${FUNCTION_NAME}"), array(STRING_LINE), false); 

기능을 분기하는 과정과 포크를 초기화

: 여기

는 일부 소스 코드입니다. 이 경우 $ callback은 적절한 클래스에서 호출 할 함수의 이름입니다. $ params는 $ callback에 지정된 함수에 전달할 매개 변수의 배열입니다.

 

    public function fork ($callback, $params = null, $hang = true) 
    { 

    $this->logger->write_log('log', "Entered fork function!"); 

      // Evaluate the return value of the fork 
     switch ($pid = pcntl_fork()) { 
      case -1: // Failed 
       $this->logger->write_log('error', "Could not fork!"); 
       exit(1); 
      break; 
      case 0: // Child created succesfully 

       $this->logger->write_log('log', "Entered child function!"); 

       $this->logger->write_log('log', 'child ' . posix_getpid() . ' started'); 
       if (empty($callback)) { 
        $this->logger->write_log('warn', "Callback empty, nothing to do!"); 
        exit(1); 
       } 

       if (is_array($callback) && is_array($params)) { 
        if (!call_user_func_array($callback, $params)) { 
         $this->logger->write_log('error', "Daemonized process returned false!"); 
         exit(1); 
        } else { 
         exit(0); 
        } 
       } else { 
        if (!call_user_func($callback, $params)) { 
         $this->logger->write_log('error', "Daemonized process returned false!"); 
         exit(1); 
        } else { 
         exit(0); 
        } 
       } 
       break; 

      default: // Parent 
       $this->logger->write_log('log', "Entered parent function!"); 
       if ($hang != true) { 
        $this->wait($pid, false); 
       } else { 
        $this->wait($pid); 
       } 
       break; 
      } 
    } 

    public function wait($p_id, $hang = true) 
    { 
     if ($hang) { 
      $pid = pcntl_waitpid($p_id, $status); 
     } else { 
      $pid = pcntl_waitpid($p_id, $status, WNOHANG); 
     } 
     switch($pid) { 
     case -1: 
     case 0: 
      $this->logger->write_log('log', "child exited"); 
      break; 
     default: 
      $this->logger->write_log('log', "child $pid exited"); 
      break; 
     } 
    } 

실제로 텍스트 줄 처리 기능.

이 너무 많은 코드가있는 경우
 
public function FUNCTION_NAME($line) { 

     $this->logger->write_log('info', 'entered FUNCTION_NAME function'); 

     $start_time = microtime(true); 

     try { 
      # check to see that the JSON line is not malformed 
      $line_array = json_decode($line, true); 
      if (!isset($line_array)) { 
       throw new Exception('Could not successfully process line'); 
      } 
      # save the contents to disk 
      if (!file_put_contents(FILE_NAME, $line, LOCK_EX)) { 
       throw new Exception('file could not be saved'); 
      } 
      $this->logger->write_log('info', 'saved line'); 
      return true; 
     } catch (Exception $e) { 
      $this->logger->write_log('error', $e->getMessage()); 
      $this->logger->write_log('error', '----------------------------------------------------'); 
      $this->logger->write_log('error', var_export($line, true)); 
      $this->logger->write_log('error', '----------------------------------------------------'); 
      file_put_contents(ERROR_SRC_FILE, $line, FILE_APPEND); 
      return false; 
     } 
    } 

죄송합니다, 원래의 질문에 대답하기 위해, 나는에 대한 제한이 발견되지 않은 나에게 질문

+2

'각 프로세스는 한 줄의 텍스트를 구문 분석하고 마지막으로 파일에 저장합니다. '- 완전히 새로운 프로세스가 필요한 것처럼 들리지는 않습니다. 왜이 방법을 사용하는지 느껴 집니까? ? – DaveRandom

+0

코드, 부모 및 자녀 중 일부를 게시하는 것이 적절할 수 있습니다. – netcoder

+0

@DaveRandom : 전체적으로 스크립트는 내가 컬로 초기화하는 텍스트 스트림을 구문 분석합니다. 스트림 검색과 구문 분석/저장 프로세스를 모두 비동기식으로 결합 했으므로 스트림을 파싱하는 데 어려움을 겪고있었습니다. 즉, 네트워크를 통해 전송 된 스트림을 처리 할 때 스트림 처리에 시간이 너무 오래 걸리고 텍스트 스트림이 대기열에 백업됩니다. 스트림을받는 원본이이 백업에 제한이 있습니다.필자는 스트리밍 프로세스에서 파싱 기능을 제거하여 시간을 절약 할 수 있기를 희망했습니다. – iralls

답변

1

으로 알려 : 텍스트의 라인은 JSON 개체입니다 을 생성 할 수있는 프로세스의 수는 생성 후 곧 사라집니다.. 나는 사용자가 리눅스에서 만들 수있는 프로세스의 한계가 있다고 생각하는데, 이는 ulimit으로 설정할 수있다.