2011-06-02 11 views
11

अब मुझे fork() सिस्टम कॉल के काम को समझने में समस्या है।सी भाषा में कांटा का काम

#include<stdio.h> 
int main() 
{ 
    int a, b; 
    b=fork(); 

    printf("\n the value of b = %d",b); 
} 

इस कोड के उत्पादन में पीछा कर रहा है: मैं एक कोड है जो पीछा कर रहा है लिखने

अब मुझे समझ नहीं आता क्यों उत्पादन इस तरह है?

उसके बाद मैं बस अपने कोड में एक लाइन जोड़ता हूं और आउटपुट पूरी तरह से अलग है। मेरी कोड पीछा कर रहा है:

int main() 
{ 
    int a, b; 
    b=fork(); 

जब मैं कोड उत्पादन 2389my नाम पीछा कर रहा है चलाने मनीष

the value of b = 0 

अब मैं पूरी तरह से fork() कॉल की कार्यप्रणाली को लेकर संदेह में हूँ है।

मेरा प्रश्न इस प्रकार हैं:

  1. कैसे fork() काम करता है?
  2. जहां नियंत्रण fork() कॉल के बाद जाता है?
  3. क्या कोई शरीर समझा सकता है कि समस्या में लिखे कोडों का आउटपुट क्यों?
  4. क्यों अलग अलग स्थानों पर होने वाली b के उत्पादन में पहले कोड में इसका मतलब है b = 2260 के उत्पादन में सिर्फ उत्पादन b = 0 से पहले है, जबकि b = 2389 का मूल्य सिर्फ b = 0 से पहले नहीं है?

कृपया मुझे समस्या में लिखे गए कोड में कांटा के काम की व्याख्या करें ताकि मैं इसे ठीक से सीख सकूं।

उत्तर

5
  1. फोर्क आपकी वर्तमान प्रक्रिया की एक प्रति बनाता है।
  2. मूल और प्रतिलिपि दोनों बिंदु से निष्पादन जारी रखते हैं जिस पर fork() कहा जाता था।
  3. क्योंकि आपका कोड दो बार निष्पादित किया गया है, इसलिए आपके प्रिंट स्टेटमेंट का मूल्यांकन दो बार किया जाता है। कॉपी की गई प्रक्रिया में, b का मान 0 है। मूल प्रक्रिया में, b का मान प्रतिलिपि प्रक्रिया की प्रक्रिया आईडी है।
  4. एक बार आपकी प्रक्रियाएं एक साथ चलने लगती हैं, तो उन्हें आपके ऑपरेटिंग सिस्टम द्वारा स्वतंत्र रूप से निर्धारित किया जाएगा और इस प्रकार आपको वास्तव में चलाने के बारे में कोई गारंटी नहीं होगी।
3
  1. forking ओएस द्वारा कार्यान्वित किया जाता है। यह मूल रूप से एक बाल प्रक्रिया बनाता है और fork() के बाद इसे चलाना शुरू कर देता है।

  2. मूल प्रक्रिया फ़ाइल प्रक्रिया की प्रक्रिया आईडी प्राप्त करती है: b=fork(); बी में प्रक्रिया आईडी है। बच्चे की प्रक्रिया शून्य का एक पिड मिलता है।

  3. (और 4) क्योंकि दोनों प्रक्रिया या तो समानांतर में चल सकती हैं या समय काटा जा सकता है, तो आपका आउटपुट अलग-अलग होगा।

यह तो आपको देखना चाहेंगे: http://en.wikipedia.org/wiki/Fork_(operating_system)

1

बेहतर होगा कि तुम this से शुरू होगी।

यहां आपको स्पष्टीकरण और कोड उदाहरण मिलते हैं।

39

इससे पहले यह समझने में मदद मिल सकती है कि इस फ़ंक्शन को नाम देने के लिए शब्द कांटा का उपयोग क्यों किया गया था। कभी "सड़क पर कांटा" के बारे में सुना? एक कांटा पर, प्रक्रिया को पथ विभाजित करना पड़ता है।

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

चूंकि आप कांटा की प्रत्येक शाखा के लिए अलग-अलग कार्य करना चाहते हैं, इसलिए यह आवश्यक है कि आप बच्चे की प्रक्रिया को मूल प्रक्रिया से अलग करने में सक्षम हों। यही वह जगह है जहां fork का वापसी मूल्य आता है: fork बच्चे की प्रक्रिया आईडी (पिड) (नव निर्मित प्रक्रिया) माता-पिता को देता है; यह बच्चे को 0 देता है। साथ ही, fork निष्पादन गलत होना चाहिए, वापसी मान -1 है।

अपने कोड में, आप बच्चे और अभिभावक प्रक्रिया के बीच अंतर नहीं करते हैं, इसलिए दोनों प्रक्रियाएं पूरे कोड को चलाती हैं जो fork कॉल के बाद होती है।

//what the child process looks like after fork is called 
int main() 
{ 
    int a, b; 
    b=fork(); // <-- current line of execution: 0 is returned to b 
    printf("\nmy name is manish\n"); 
    printf("\n my name is anil\n"); 
    printf("\n the value of b = %d",b); 
} 

// what the parent process looks like after fork is called 
int main() 
{ 
    int a, b; 
    b=fork(); // <-- current line: child process id is returned 
    printf("\nmy name is manish\n"); 
    printf("\n my name is anil\n"); 
    printf("\n the value of b = %d",b); 
} 

आप देख सकते हैं, दोनों प्रक्रियाओं एक ही कोड कांटा निम्नलिखित है, इसलिए उत्पादन दोहराया है की है। आप उत्पादन मनीष को माता-पिता की प्रक्रिया और उत्पादन अनिल के लिए बच्चे चाहते हैं शायद अगर है, तो आप की तरह कुछ कर सकते हैं:

int main() 
{ 
    pid_t b; // note that the actual return type of fork is 
      // pid_t, though it's probably just an int typedef'd or macro'd 

    b = fork(); 
    if (b == -1) perror("Fork failed"); 
    else if (b > 0) { 
     printf("My name is Manish\n"); // parent process 
    else 
     printf("My name is Anil\n"); // child process 

    printf("The value of b is %d\n", b); 
    return 0; 
} 

अंत में, अंतिम टिप्पणी है कि किया जाना चाहिए अपने कोड में, उत्पादन के लिए प्रकट होता है पहली बार एक प्रक्रिया द्वारा पूरी तरह से निष्पादित किया गया है और फिर दूसरी प्रक्रिया पूरी तरह से निष्पादित की गई है। यह हमेशा मामला नहीं हो सकता है। उदाहरण के लिए, ऑपरेटिंग सिस्टम माता-पिता को 'मनीष' आउटपुट निष्पादित करने की अनुमति दे सकता है, फिर इस प्रक्रिया को प्रतीक्षा कर सकता है, और सीपीयू को बाल प्रक्रिया में सौंप सकता है, जो तब 'मनीष' निष्पादित करता है। हालांकि, बाल प्रक्रिया जारी रख सकती है और 'अनिल' और 'बी' आउटपुट निष्पादित कर सकती है, बाल प्रक्रिया के निष्पादन को पूरा कर सकती है और इस प्रकार निष्पादन को मूल प्रक्रिया में वापस कर सकती है। अब माता-पिता 'अनिल' और 'बी' को आउटपुट करके अपने निष्पादन को समाप्त कर देते हैं।

 
my name is manish  // executed by parent 
my name is anil  // child 
the value of b = 0 // child 
my name is anil  // parent 
the value of b = 2244 // parent 
[email protected]-lin:~$ 

fork के लिए आदमी पृष्ठ पर एक नज़र डालें: इस कार्यक्रम चलाने का अंतिम आउटपुट की तरह कुछ लग सकता है। पेरेंट प्रक्रियाओं द्वारा बाल प्रक्रियाओं के उचित संचालन के लिए waitpid पर भी देखें ताकि आप ज़ोंबी न बनाएं।

संपादित करें: टिप्पणियों में आपके प्रश्नों के जवाब में, मैं जवाब दूंगा कि आप प्रत्येक प्रक्रिया को लगातार कैसे चला सकते हैं।

int main() 
{ 
    pid_t pid; 
    int i; 

    for (i=0; i<NUM_PROCESSES; i++) 
    { 
     pid = fork(); 
     if (pid == -1) 
     { 
      perror("Error forking"); 
      return -1; 
     } 
     else if (pid > 0) 
     { 
      // parent process 
      waitpid(-1, NULL, 0); //might want to look at man page for this 
            // it will wait until the child process is done 
     } 
     else 
     { 
      // do whatever each process needs to do; 
      // then exit() 
      doProcess(i); 
      exit(0); 
     } 
    } 
    // do anything else the parent process needs to do 
    return 0; 
} 

बेशक, सबसे अच्छा कोड नहीं है, लेकिन यह केवल बिंदु को चित्रित करने के लिए है। यहां बड़ा विचार waitpid कॉल है, जो माता-पिता की प्रक्रिया को तब तक प्रतीक्षा करने का कारण बनता है जब तक बच्चे इसे संसाधित नहीं करता fork ed समाप्त करने के लिए।बच्चे की प्राप्ति पूर्ण होने के बाद, माता-पिता waitpid कॉल के बाद जारी रहता है, for लूप का एक और पुनरावृत्ति शुरू करता है और दूसरी (अगली) प्रक्रिया को फोर्क करता है। यह तब तक जारी रहता है जब तक कि सभी बाल प्रक्रियाओं ने अनुक्रमिक रूप से निष्पादित नहीं किया है और अंततः निष्पादन माता-पिता को वापस आ जाता है।

+2

@ गोल्लू फोर्किंग का विचार था इसलिए प्रक्रियाएं एक साथ चल सकती थीं। यदि आप उन्हें अनुक्रम में चलाने के लिए चाहते हैं (जो किया जा सकता है, यह नहीं कह सकता कि वे नहीं कर सकते हैं), क्यों पहली जगह फोर्किंग परेशान करते हैं? क्या अनुक्रम में प्रक्रियाओं को चलाकर आप एक बड़ा लक्ष्य हासिल करने की कोशिश कर रहे हैं? – ladaghini

+0

बकाया उत्तर! –

+0

आपके उदाहरण में 'बी = 0 // पैरेंट' का मान। क्या इसे इसके बजाय 'बी = 0 // बच्चे' का मूल्य पढ़ना चाहिए? – srkrish

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