मैं fork() का परीक्षण करने के लिए यह छोटा प्रोग्राम चलाता हूं, और मैं आउटपुट का पता नहीं लगा सकता, प्रोग्राम का कोड है:

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 

int i = 0;
void create()
{
    fork();
    printf("Inside i= %d \n", i);
    i = i + 1;
    fork();
}
int main()
{
    create();  
    return 0;
}

आउटपुट है:

Inside i= 0 
Inside i= 0 
Inside i= 0 
Inside i= 0 

क्या केवल दो आउटपुट नहीं होने चाहिए, क्योंकि अंतिम fork() में, बच्चों के पास प्रिंट आउट करने के लिए कुछ नहीं है?

मैंने पढ़ा है कि प्रक्रिया बच्चा fork() के बाद अगला निर्देश निष्पादित करेगा, हालांकि अंतिम बच्चों ने printf() निर्देश निष्पादित किया है।

6
OussamaMater 22 जिंदा 2020, 16:12

1 उत्तर

सबसे बढ़िया उत्तर

आपके कार्यक्रम का आउटपुट अत्यधिक कार्यान्वयन पर निर्भर है।

सी मानक पुस्तकालय आउटपुट स्ट्रीम में बफरिंग लागू करता है। इसका मतलब यह है कि यह लिखने के लिए वर्णों को तब तक जमा करता है जब तक कि बफर एक निश्चित लंबाई तक नहीं पहुंच जाता (या एक निश्चित शर्त पूरी होने तक), और फिर एक ही बार में सभी टेक्स्ट को आउटपुट करता है।

सबसे आम व्यवहार लाइन बफ़रिंग का उपयोग करना है, जिसका अर्थ है कि जब एक नई पंक्ति वर्ण (\n) का सामना करना पड़ता है, तो टेक्स्ट प्रिंट हो जाएगा। यह वास्तव में आपके उदाहरण के साथ मेरी मशीन पर होता है। चूंकि आप fork() से पहले printf(), दो प्रक्रियाएं कॉल को निष्पादित करती हैं और आउटपुट तुरंत प्रिंट हो जाता है क्योंकि एक नई लाइन है:

$ ./prog
Inside i= 0
Inside i= 0

अन्य fork() को दो प्रक्रियाओं में से प्रत्येक पर निष्पादित किया जाता है, लेकिन प्रिंट आउट करने के लिए और कुछ नहीं है, क्योंकि आंतरिक आउटपुट बफर पहले ही खाली हो चुका है, इसलिए इस मामले में कुछ भी ध्यान देने योग्य नहीं है।

हालांकि, आपके विशिष्ट कार्यान्वयन और उन शर्तों के आधार पर जिनमें प्रोग्राम चलाया जाता है, printf() (और सामान्य तौर पर कोई भी stdio फ़ंक्शन) अलग-अलग बफरिंग नियम लागू करने का निर्णय ले सकता है।

उदाहरण के लिए, आउटपुट को किसी अन्य प्रोग्राम या फ़ाइल में पाइप करते समय, ग्लिबैक आमतौर पर एक निश्चित आकार के बफर का उपयोग करता है और लाइन बफरिंग नहीं करता है। चूंकि बफ़र एक भी शॉर्ट printf() से भरा नहीं है, इसलिए टेक्स्ट को बाद में प्रिंट करने के लिए इसके अंदर रखा जाता है। जब आप दूसरी बार fork() करते हैं, तो प्रत्येक नए बच्चे को उक्त बफर की एक प्रति मिलती है, और प्रक्रिया समाप्त होने पर सभी पाठ (उनमें से प्रत्येक द्वारा) मुद्रित किया जाता है। मेरे सिस्टम पर, पाइपिंग करते समय, यह आउटपुट होता है:

$ ./prog | cat
Inside i= 0
Inside i= 0
Inside i= 0
Inside i= 0

अगर आप यह सुनिश्चित करना चाहते हैं कि टेक्स्ट तुरंत प्रिंट हो जाए, तो आप fflush() या setvbuf().

उदाहरण:

  • fflush() का उपयोग करना:

    void create()
    {
        fork();
        printf("Inside i= %d \n", i);
        fflush(stdout);
        i = i + 1;
        fork();
    }
    
  • setvbuf() का उपयोग करना:

    int main()
    {
        setvbuf(stdout, NULL, _IONBF, 0);
        create();  
        return 0;
    }
    
14
Marco Bonelli 10 अक्टूबर 2020, 17:50