कांटा () उम्मीद से ज्यादा शाखाएं?


186

निम्नलिखित कोड कोड पर विचार करें:

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

int main(void)
{
    int i;
    for(i = 0; i < 2; i++)
    {
        fork();
        printf(".");
    }
    return 0;
}

यह प्रोग्राम 8 डॉट्स आउटपुट करता है। वह कैसे संभव हो सकता है? क्या इसके बदले 6 डॉट्स नहीं होने चाहिए?



जवाबों:


245

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

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

हालांकि, printf()वास्तव में क्या करता है इसका उत्पादन बफर है। तो पहले डॉट जब केवल दो प्रक्रियाएं थीं, जब लिखित नहीं होती हैं। वे डॉट्स बफ़र में रहते हैं - जो कि फोर्क () में डुप्लिकेट है। यह तब तक नहीं है जब तक यह प्रक्रिया बाहर निकलने वाली नहीं है कि बफ़र्ड डॉट दिखाई देता है। चार प्रक्रियाएं एक बफ़र्ड डॉट को प्रिंट करती हैं, साथ ही नया एक 8 डॉट्स देता है।

आपको लगता है कि व्यवहार से बचना चाहते थे, तो फोन fflush(stdout);के बाद printf()


12
धन्यवाद, मुझे नहीं पता था कि बफर फोर्क () के साथ डुप्लिकेट करता है। यह इस तरह के एक अजीब व्यवहार की व्याख्या करता है।
निकोले कोवलेंको

1
कि 10 डॉट्स नहीं देना चाहिए, 8 नहीं? चूँकि 4 सेकंड जनरेशन के बच्चों को बफर डॉट विरासत में मिलती है, इसलिए अपना स्वयं का जोड़ें, फिर बाहर निकलने पर फ्लश करें, वे कुल 8 डॉट्स प्रिंट करेंगे, लेकिन तब 2 पहली पीढ़ी की प्रक्रियाओं में अभी भी एक डॉट प्रत्येक बफर होगा, और बाहर निकलने पर फ्लश करें, कुल 10.
psusi

12
@psusi दूसरी पीढ़ी की प्रक्रियाओं में से एक पहली पीढ़ी की प्रक्रिया है। fork()2 से बाहर न निकलें, यह केवल 1 और प्रक्रिया बनाता है।
इजाकाता

70

आपने आउटपुट स्ट्रीम में अनफ़ॉर्म किए गए बफ़र्स हैं । स्टडआउट लाइन-बफ़र्ड है, और बफ़र को बाकी प्रक्रिया के साथ दोहराया जाता है। जब प्रोग्राम समाप्त हो जाता है, तो अनकम्फर्ड बफर दो बार (प्रत्येक प्रक्रिया के लिए एक बार) लिखा जाता है। दोनों का उपयोग कर

printf("a\n");

तथा

printf("a "); fflush(stdout);

समस्या का प्रदर्शन न करें।

अपने पहले उदाहरण में, आप चार प्रक्रियाएँ बनाते हैं जिनके प्रत्येक दो बिंदु उनके आउटपुट स्ट्रीम बफर में होते हैं। जब प्रत्येक धारा समाप्त हो जाती है, तो वह अपने बफर को फ्लश करती है, जिससे आठ डॉट्स बनते हैं।


2

जब मैं = ०

प्रक्रिया 1: बफर पाठ = 1 डॉट

Process_2 (Process_1 द्वारा बनाई गई): बफर टेक्स्ट = 1 डॉट

जब मैं = १

Process_3 (Process_1 द्वारा बनाया गया): Process_1 से 1 बफ़र्ड डॉट इनहेरिट करें और 1 बिंदी को अपने आप प्रिंट करता है। कुल Process_3 में 2 डॉट्स प्रिंट होते हैं।

Process_4 (Process_2 द्वारा बनाई गई): Process_2 से 1 बफ़र्ड डॉट इनहेरिट करें और 1 बिंदी को अपने आप प्रिंट करता है। कुल Process_4 में 2 डॉट्स प्रिंट होते हैं।

प्रक्रिया 1: प्रिंट 2 डॉट्स (एक बफर डॉट जब मैं = 0 और दूसरा डॉट जब मैं = 1)

प्रक्रिया 2: प्रिंट 2 डॉट्स (एक बफर डॉट जब मैं = 0 और दूसरा डॉट जब मैं = 1)

अंतिम आउटपुट: 8 डॉट्स। :)

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