2010-02-16 16 views
8

मैं एक स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो pcntl_* functions का उपयोग करके कई फोर्कड बाल प्रक्रियाएं बनाता है।PHP फोर्किंग और एकाधिक बाल सिग्नल

असल में, एक ही स्क्रिप्ट है जो लगभग एक मिनट के लिए एक लूप में चलती है, समय-समय पर डेटाबेस को मतदान करने के लिए यह देखने के लिए कि क्या कोई कार्य चलाना है या नहीं। यदि कोई है, तो इसे एक अलग प्रक्रिया में फोर्क और रन करना चाहिए ताकि माता-पिता लंबे समय तक चलने वाले कार्य से नहीं हो सकें।

चूंकि संभावित रूप से बड़ी संख्या में कार्य चलाने के लिए तैयार हो सकते हैं, इसलिए मैं बनाए गए बाल प्रक्रियाओं की संख्या को सीमित करना चाहता हूं। इसलिए, मैं प्रत्येक बार बनाए गए एक चर को बढ़ाकर प्रक्रियाओं की संख्या का ट्रैक रख रहा हूं (और फिर बहुत अधिक होने पर रोक रहा है), और उसके बाद सिग्नल हैंडलर में इसे कम किया जा रहा है। एक तरह से इस तरह:

define(ticks = 1); 

$openProcesses = 0; // how many we have open 
$max = 3;   // the most we want open at a time 

pcntl_signal(SIGCHLD, "childFinished"); 

while (!time_is_up()) { 
    if (there_is_something_to_do()) { 
     $pid = pcntl_fork(); 
     if (!$pid) {  // I am the child 
      foo();  // run the long-running task 
      exit(0);  // and exit 
     } else {   // I am the parent 
      ++$openProcesses; 
      if ($openProcesses >= $max) { 
       pcntl_wait($status); // wait for any child to exit 
      }       // before continuing 
     } 
    } else { 
     sleep(3); 
    } 
} 

function childFinished($signo) { 
    global $openProcesses; 
    --$openProcesses; 
} 

यह काफी ठीक समय के सबसे अधिक काम करता है, के लिए जब दो या अधिक प्रक्रियाओं एक साथ खत्म छोड़कर - संकेत हैंडलर समारोह केवल एक बार कहा जाता है, जो मेरे काउंटर बाहर फेंकता है। इस का कारण यह notes of the PHP manual में "बेनामी" द्वारा समझाया गया है:

एकाधिक बच्चों को एक भी क्षण SIGCHLD संकेतों पर बाहर निकलने बच्चों की संख्या की तुलना में कम यूनिक्स (POSIX) सिस्टम के लिए सामान्य व्यवहार है लौटने। सिगचेल को पढ़ा जा सकता है "एक या अधिक बच्चों ने स्थिति बदल दी - अपने बच्चों की जांच करें और उनके स्टेटस वैल्यू फसल करें"।

मेरा प्रश्न यह है: मैं बच्चों की जांच कैसे कर सकता हूं और उनकी स्थिति कैसे फसल कर सकता हूं? क्या किसी भी समय पर कितनी बाल प्रक्रियाएं खुली हैं, यह जांचने का कोई भरोसेमंद तरीका है?

पीएचपी 5.2.9

+0

शायद सिर्फ https://www.rabbitmq.com/ का उपयोग कर पूरी बात बहुत कम गलतियाँ होगा –

उत्तर

0

का उपयोग करते हुए आप बच्चों के माता पिता के लिए एक SIGUSR1 भेज जब वे शुरू हो सकता था, तो एक SIGUSR2 वे बाहर निकलने से पहले। आदिम संकेतों का उपयोग करते समय आप जिस अन्य चीज से निपट रहे हैं वह कर्नेल उन्हें विलय कर रहा है, जो आरटी सिग्नल के साथ नहीं करता है। सिद्धांत रूप में, किसी भी गैर-आरटी संकेत विलय किया जा सकता है।

आप स्क्लाइट का उपयोग करके किसी प्रकार का सरल लॉकिंग लागू कर सकते हैं, जहां एक समय में केवल एक बच्चे को बात करने वाली छड़ी हो सकती है। बस सुनिश्चित करें कि बच्चे सामान्य रूप से घातक संकेतों को संभालते हैं ताकि वे ताला मुक्त करने के लिए जीवित रहें।

2

एक तरीका है बाल प्रक्रियाओं के पीआईडी ​​की सरणी रखना, और सिग्नल हैंडलर में प्रत्येक पीआईडी ​​को यह देखने के लिए जांचें कि यह अभी भी चल रहा है या नहीं। (Untested) कोड दिखाई देगा:

define(ticks = 1); 

$openProcesses = 0; 
$procs = array(); 
$max = 3; 

pcntl_signal(SIGCHLD, "childFinished"); 

while (!time_is_up()) { 
    if (there_is_something_to_do()) { 
     $pid = pcntl_fork(); 
     if (!$pid) {  
      foo();   
      exit(0);  
     } else {   

      $procs[] = $pid; // add the PID to the list 

      ++$openProcesses; 
      if ($openProcesses >= $max) { 
       pcntl_wait($status);  
      }       
     } 
    } else { 
     sleep(3); 
    } 
} 

function childFinished($signo) { 

    global $openProcesses, $procs; 

    // Check each process to see if it's still running 
    // If not, remove it and decrement the count 
    foreach ($procs as $key => $pid) if (posix_getpgid($pid) === false) { 
     unset($procs[$key]); 
     $openProcesses--; 
    } 

} 
संबंधित मुद्दे