कांटा () के बाद, बच्चा अपना निष्पादन कहां से शुरू करता है?


22

मैं UNIX प्रोग्रामिंग सीखने की कोशिश कर रहा हूं और कांटा () के बारे में एक सवाल आया है। मैं समझता हूं कि कांटा () वर्तमान में चल रही प्रक्रिया की एक समान प्रक्रिया बनाता है, लेकिन यह कहां से शुरू होता है? उदाहरण के लिए, यदि मेरे पास कोड है

int main (int argc, char **argv)
{
    int retval;
    printf ("This is most definitely the parent process\n");
    fflush (stdout);
    retval = fork ();
    printf ("Which process printed this?\n");

    return (EXIT_SUCCESS);
}

आउटपुट है:

यह निश्चित रूप से मूल प्रक्रिया है
जो इस प्रक्रिया को मुद्रित करती है?
किस प्रक्रिया ने इसे छापा?

मैंने सोचा कि fork()यह एक ही प्रक्रिया बनाता है, इसलिए मैंने शुरू में कहा था कि उस कार्यक्रम में, fork()कॉल को पुनरावर्ती रूप से हमेशा के लिए कहा जाएगा। मुझे लगता है कि कॉल के fork()बाद से बनाई गई नई प्रक्रिया शुरू होती है fork()?

यदि मैं एक माता-पिता और बच्चे की प्रक्रिया के बीच अंतर करने के लिए, निम्न कोड जोड़ता हूं,

if (child_pid = fork ()) printf ("This is the parent, child pid is %d\n", child_pid);
else printf ("This is the child, pid is %d\n",getpid ());

कांटा () कॉल के बाद, बच्चे की प्रक्रिया कहां से शुरू होती है?


5
man forkआपके सवाल का जवाब देने के लिए पर्याप्त है, btw
एलेक्स

जवाबों:


23

नई प्रक्रिया fork()कॉल के भीतर बनाई जाएगी , और यह माता-पिता की तरह से वापस आने से शुरू होगी। वापसी मूल्य (जो आपने में संग्रहीत किया है retval) fork()होगा:

  • बच्चे की प्रक्रिया में 0
  • माता-पिता की प्रक्रिया में बच्चे का पीआईडी
  • -1 माता-पिता में अगर कोई विफलता थी (स्वाभाविक रूप से कोई बच्चा नहीं है)

आपका परीक्षण कोड सही ढंग से काम करता है; इसमें से रिटर्न वैल्यू को स्टोर किया fork()जाता है child_pidऔर ifयह जांचने के लिए उपयोग किया जाता है कि यह 0 है या नहीं (हालांकि यह एक त्रुटि की जांच नहीं करता है)


13

मैंने सोचा था कि कांटा () एक ही प्रक्रिया बनाता है, इसलिए मैंने शुरू में कहा था कि उस कार्यक्रम में, कांटा () कॉल पुनरावर्ती हमेशा के लिए कहा जाएगा। मुझे लगता है कि कांटा () कॉल से नई प्रक्रिया शुरू होती है?

हाँ। चलो लाइनों की संख्या:

int main (int argc, char **argv)
{
    int retval;                                               /* 1 */
    printf ("This is most definitely the parent process\n");  /* 2 */
    fflush (stdout);                                          /* 3 */
    retval = fork ();                                         /* 4 */
    printf ("Which process printed this?\n");                 /* 5 */
    return (EXIT_SUCCESS);                                    /* 6 */
}

निष्पादन प्रवाह है:

caller process     fork()  ...
                          
original program            exec()  2  3  4  5  6
                                               
forked program                                   5  6

... जो आपको प्राप्त आउटपुट के बारे में बताता है।

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


ध्यान दें कि 1 वास्तव में एक निर्देश नहीं है। यह भी ध्यान दें कि मूल और कांटेक्ट प्रोग्राम वास्तव में एक ही समय में नहीं चलते हैं - या तो दूसरे को उपज के लिए इंतजार करना होगा / पहले से तैयार रहना होगा।
12

1
मल्टी-कोर / मल्टी-सीपीयू सिस्टम पर, दोनों प्रोग्राम वास्तव में एक ही समय में चल सकते हैं।
जुलैग्रे

@jilliagre मल्टीकोर सिस्टम वास्तव में मल्टीथ्रेडिंग के बारे में हैं। कई सीपीयू के साथ सिस्टम के लिए, मुझे नहीं पता कि यह मामला है या व्यवहार में नहीं है। मैं इस क्षेत्र में कोई विशेषज्ञ नहीं हूँ - और यह सिर्फ इस तरह के एक असंभावित परिदृश्य की तरह लगता है। यदि हम सहमत हैं कि OS एक ही समय में कई प्रक्रियाएँ चला सकता है (तब यह समवर्ती कैसे संभालेगा?), जब तक मूल कार्यक्रम सीपीयू पर निर्देश 4 नहीं चलता, तब तक अन्य सीपीयू वैसे भी अन्य प्रक्रियाओं को चलाने में व्यस्त रहते हैं ।
badp

मैं कहूंगा कि यह एक बहुत ही संभावित परिदृश्य है, विशेष रूप से कुछ I / O चरण 5 में होने के साथ एक अंतर्निहित प्रणाली कॉल है। सभी CPU व्यस्त होना वास्तव में एक सामान्य स्थिति नहीं है क्योंकि CPU शायद ही कभी वर्तमान मशीनों के साथ अड़चन है। ऐसा लगता है कि आप मल्टी-थ्रेडिंग और मल्टी-कोर को भ्रमित कर रहे हैं।
jlliagre

8
क्या मैं सिर्फ यह कहने के लिए टिप्पणी कर सकता हूं कि विकर्ण तीर शानदार हैं
जेबीर्च

0

इसका वास्तविक समाधान है

switch (fork()) {
    case -1 :
        fprintf (stderr, "fork failed (%s)\n", strerror(errno));
        break;
    case 0 :  // child process comes here
        break;
    default : // parent process
        break;
}

// all continue here

-1

जो भी कोड हो उसके बाद fork(), बच्चे की प्रक्रिया में कॉपी किया जाता है, और माता-पिता और बच्चे की प्रक्रिया को नहीं मिलाते हैं, वे दो अलग-अलग संस्थाएं हैं, जिनके पास समान (दोहराए गए, साझा नहीं किए गए) वातावरण हैं।

अब देखिए आपका आउटपुट ...

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.