2011-03-19 14 views
14

यह लिनक्स में सी के बारे में है।फोर्क - एक ही मेमोरी पते?

मेरे पास fork()main() में है जहां मैं 2 बाल प्रक्रियाएं बनाता हूं। फिर, दोनों बच्चे प्रक्रिया में एक रन abc() चलाएं, जहां स्थानीय चर x है। मैं इसमें कुछ मूल्य लिखता हूं। फिर मैं इस चर के पते को printf("%p",&x) के साथ प्रिंट करता हूं।

दोनों प्रक्रियाएं एक ही पते को मुद्रित करती हैं। मैंने सोचा कि हर बच्चे को माता-पिता की स्मृति की एक (स्वतंत्र) प्रति प्राप्त होती है। मुझे अपनी प्रक्रिया x रखने के लिए हर प्रक्रिया की आवश्यकता है। मैं यह कैसे कर सकता हूं या मैं कुछ गलत कर रहा हूं?

उत्तर

20

आपको यह समझने की आवश्यकता है कि भौतिक स्मृति और प्रक्रिया के वर्चुअल एड्रेस स्पेस के बीच डिस्कनेक्ट है।

प्रत्येक एकल प्रक्रिया को अपने 4 जी आभासी पता स्थान प्राप्त होता है और यह आपके वर्चुअल पतों को भौतिक लोगों को मैप करने के लिए ऑपरेटिंग सिस्टम और हार्डवेयर मेमोरी प्रबंधकों का काम है।

तो, जबकि यह लग सकता है कि दो प्रक्रियाओं एक चर के लिए एक ही पता है, कि केवल आभासी पता है।

मेमोरी मैनेजर इसे पूरी तरह से अलग भौतिक पता पर मैप करेगा।

यह मैपिंग भी आपको दस प्रक्रियाओं को चलाने की अनुमति देता है, प्रत्येक 1 जी लेता है, भले ही आपकी मशीन में केवल 4 जी भौतिक स्मृति हो। ओएस डिस्क पर आपकी मेमोरी के बिट्स को स्वैप कर सकता है और जब आप उनका उपयोग करने का प्रयास करते हैं तो उन्हें वापस ला सकते हैं।


एक: अधिकांशतः, यह सच है। यदि आप प्रक्रियाओं के बीच सामान साझा कर रहे हैं तो यह उसी भौतिक पते पर मैप कर सकता है। उदाहरण के लिए, साझा स्मृति, कर्नेल कोड और डेटा, गतिशील पुस्तकालय और बहुत आगे।

+9

दरअसल यह सभी एक ही भौतिक पते पर नक्शा रखेगा जब तक प्रतिलिपि लिखने न हो। –

+0

धन्यवाद, मैं इसे समझता हूं। – Asheron2332

+0

@R, मैं दावा करूंगा कि अंत में "और बहुत आगे" बिट के हिस्से के रूप में :-) – paxdiablo

2

वर्चुअल मेमोरी सिस्टम की वजह से, प्रत्येक बच्चे की प्रक्रियाओं में एक ही (आभासी) पता के साथ अपना स्वयं का चर होता है।

वही आभासी पते एक ही भौतिक स्थान पर इंगित नहीं करेंगे।

5

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

+0

मुझे लगता है कि कांटे के मापने योग्य दुष्प्रभाव वास्तव में कांटा के समय वर्चुअल एड्रेस स्पेस का हिस्सा नहीं हैं। – Neil

+0

"किसी फ़ाइल में सहेजे गए पते" को तोड़ दिया जा सकता है यदि एक नई प्रक्रिया (सामान्य रूप से) में लोड किया जाता है, तो यह शायद 'फोर्क' पर प्रतिबंध नहीं है। लेकिन मेमोरी में जटिल सूचक-डेटा संरचना का उपयोग करना बरकरार रखा जाना चाहिए। –

+0

@ बेन: यदि एक ही प्रक्रिया में फिर से लोड नहीं किया गया है या उसी प्रक्रिया के फोर्कड वंशज नहीं हैं जिन्हें 'exec' नहीं कहा गया है। –

1

यह समझने के लिए कि यह कैसे हो सकता है आपको लिनक्स की प्रक्रिया/थ्रेड मॉडल को समझने की आवश्यकता है। लिनक्स यूनिक्स से विरासत में प्राप्त कांटा-और-निष्पादन मॉडल का पालन करता है। इस मॉडल में कांटा() सिस्टम कॉल द्वारा उत्पन्न प्रक्रिया थ्रेड और विंडोज प्रक्रिया के बीच एक क्रॉस का कुछ है।

जब धागा उत्पन्न होता है (लिनक्स या विंडोज में कोई फर्क नहीं पड़ता), तो नया धागा माता-पिता के साथ अपना पता स्थान साझा करता है। दोनों एक ही पते पर पहुंच कर एक ही वस्तुएं पा सकते हैं। लेकिन ये धागे विभिन्न ढेर का उपयोग करते हैं।नतीजतन दोनों धागे के स्थानीय चर के समान पते नहीं होने की गारंटी है।

जब विंडोज वातावरण में प्रक्रिया उत्पन्न होती है, तो ओएस स्क्रैच से पूरी तरह से नया पता स्थान बनाता है और इसे स्मृति और डेटा की आवश्यकता से पॉप्युलेट करता है। सिद्धांत रूप में, दोनों प्रक्रियाओं के स्थानीय चर के समान पते हो सकते हैं लेकिन अभ्यास की संभावना बहुत कम होगी। और यहां तक ​​कि जब दोनों चर एक ही पते का उपयोग करेंगे, तो ये दो चर अभी भी अलग-अलग वस्तुएं होंगी।

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

आपके मामले में आपके पास दो बच्चे हैं जो एक ही स्टैक की दो प्रतियों के साथ हैं, जिन पर स्थानीय चर समान पते पर संग्रहीत होते हैं लेकिन अलग-अलग पता रिक्त स्थान पर होते हैं। फिर आपने दोनों बच्चों पर एक ही कोड चलाया है। दूसरे शब्दों में आपके पास स्टैक लेआउट की एक ही प्रारंभिक स्थिति है और उसी कोड को चलाता है जो इस लेआउट को उसी तरह संशोधित करता है। नतीजतन आप एक ही पते पर स्थित एक ही स्थानीय चर होगा।

0

चूंकि आप स्टैक वेरिएबल (स्थानीय चर) के पते को प्रिंट कर रहे हैं। इसका पता वही होगा (इससे कोई फर्क नहीं पड़ता कि आप इसका मूल्य अपडेट करते हैं या नहीं)। चूंकि दोनों प्रक्रियाएं एक सामान्य वर्चुअल स्टैक साझा करती हैं।

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

+0

क्या कोई कारण है कि आप 3.5 साल के पुराने प्रश्न पर पोस्ट कर रहे हैं? कृपया "मुझे भी" उत्तर से बचने का प्रयास करें। –

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