2012-02-20 6 views
56

मैं एक साधारण प्रोग्राम है। यह एक Hello world के बजाय क्यों होता है? मुझे लगता है कि बच्चे की प्रक्रिया दृश्यों के पीछे फिर से चल रही है और आउटपुट बफर प्रक्रियाओं या उन पंक्तियों के साथ कुछ साझा किया जाता है, लेकिन क्या यह मामला है या कुछ और हो रहा है?कांटा() और आउटपुट

+2

यह वही है जो यह माता-पिता की स्मृति के साथ प्रक्रिया को जन्म देता है। http://linux.die.net/man/2/fork – v01d

+2

यकीन है कि हाल ही में बहुत सारे 'कांटा() 'प्रश्न रहे हैं ... हम्म ... – Mysticial

+4

मैं साक्षात्कार गंध करता हूं: पी –

उत्तर

91

यह मूल रूप से आपने जो सोचा था वह बिल्कुल नहीं है। आउटपुट बफर साझा नहीं किया जाता है - जब आप कांटा निष्पादित करते हैं, दोनों प्रक्रियाओं को एक ही बफर की एक प्रति प्राप्त होती है। तो, आपके फोर्क के बाद, दोनों प्रक्रियाएं अंततः बफर को फ्लश करती हैं और सामग्रियों को अलग-अलग स्क्रीन पर प्रिंट करती हैं।

यह केवल इसलिए होता है क्योंकि cout buffered IO है। यदि आपने सीर का उपयोग किया है, जिसे बफर नहीं किया गया है, तो आपको केवल एक बार संदेश देखना चाहिए, प्री-कांटा।

+6

यह केवल इसलिए होता है क्योंकि cout उपयोगकर्ताpace-buffered IO है।^_ ^ –

9

यदि आप का उपयोग करें:

std::cout << " Hello World" << std::flush; 

आप केवल एक ही देखते हैं। मुझे लगता है कि fork() कॉपी करता है जो आउटपुट बफर std::cout लिखता है।

6

स्ट्रिंग को तुरंत स्क्रीन पर नहीं लिखा गया है; इसके बजाय, यह एक आंतरिक बफर को लिखा गया है। बाल प्रक्रिया को आउटपुट बफर की एक प्रति प्राप्त होती है, इसलिए जब बच्चे का cout स्वचालित रूप से फ़्लश हो जाता है, तो Hello World स्क्रीन पर मुद्रित होता है। माता-पिता भी Hello World प्रिंट करता है।

यदि आप fork() से पहले cout फ़्लश करते हैं, तो समस्या लगभग निश्चित रूप से दूर हो जाएगी।

+1

मैं नहीं कहूंगा कि विश्लेषण बिल्कुल सही है। बाल प्रक्रिया "दृश्यों के पीछे पीछे नहीं आती है।" –

+0

@MichaelMior: आप सही हैं। मैं "पुनः चलाने" बिट याद किया। मैंने भाषा संपादित की है। – NPE

43

मानक आउटपुट buffered IO का उपयोग करता है। जब fork() को मानक आउटपुट कहा जाता है तो उसे फ्लश नहीं किया जाता है और बफर्ड सामग्री को बाल प्रक्रिया में दोहराया जाता है। प्रक्रिया से बाहर निकलने पर ये बफर फ़्लश किए जाते हैं, जिसके परिणामस्वरूप आप दो आउटपुट देखते हैं।

आप के लिए कार्यक्रम को बदलते हैं:

std::cout << " Hello World;" << std::endl; 

आप केवल एक देखना चाहिए।

+2

यह उत्तर मुझे सबकुछ स्पष्ट करता है। बड़ा धन्यवाद दो बार – Tebe

17

क्योंकि आपने पहले सभी बफर को फ्लश किए बिना फोर्क() कहा था।

cout.flush(); 
fork(); 
2

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

10

आउटपुट "Hello World" आउटपुट को केवल एक बार निष्पादित किया जाता है। मुद्दा यह है कि आउटपुट बफर फ्लश नहीं किया जाता है। तो जब आप प्रक्रिया को फोर्क करते हैं, तो "Hello World" अभी भी आउटपुट बफर में बैठा है। जब दोनों प्रोग्राम बाहर निकलते हैं, तो उनके आउटपुट बफर फ़्लश हो जाएंगे और आप आउटपुट को दो बार देखेंगे।

इसका प्रदर्शन करने का सबसे आसान तरीका आपकी स्ट्रिंग के अंत में एक नई लाइन जोड़ना है, जो एक अंतर्निहित फ्लश का कारण बनता है, या स्पष्ट रूप से std::cout.flush(); के साथ फ्लश करेगा। फिर आप केवल एक बार आउटपुट देखेंगे।

3

कारण यह है कि जब आप std::cout<< का आह्वान करते हैं तो यह वास्तव में आउटपुट स्वयं नहीं करता है लेकिन सिस्टम में बफर में डेटा छोड़ा जाता है। जब आप कांटा करते हैं, तो दोनों कोड और डेटा की प्रतिलिपि बनाई जाती है, साथ ही साथ जुड़े सभी बफर भी होते हैं। अंत में, पिता और पुत्र दोनों मानक आउटपुट में फिसलते हैं और इस प्रकार आप आउटपुट डुप्लीकेट देखते हैं।

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