2011-08-31 12 views
8

यहाँ मेरी कोडक्यों बच्चे प्रक्रिया और माता पिता की प्रक्रिया के चर का पता एक ही है

int main() 
{ 
    pid_t pid; 
    int y = 3; 
    if ((pid = fork()) <0) 
    return -1;; 

    if(pid == 0) /* child */ 
    { 
    printf(" before: %d %p\n", y, &y); 
    y *= 10; 
    printf("after: %d %p\n", y, &y); 
    } 
    else /* father */ 
    { 
    sleep(1); 
    printf("father: %d %p\n" , y , &y); 

    } 
    return 0; 
} 

है कार्यक्रम के उत्पादन की तरह निम्नलिखित है: है

before: 3 ffbff440 
after: 30 ffbff440 
father: 3 ffbff440 

मेरा प्रश्न क्यों का पता है बच्चे और माता-पिता का चर समान है लेकिन मूल्य अलग है?

उत्तर

21

क्योंकि यह एक आभासी पता है, न कि भौतिक एक है।

प्रत्येक प्रक्रिया (उदाहरण के लिए, एक 32-बिट प्रणाली प्रत्येक प्रक्रिया पूर्ण 4 जी श्रृंखला के साथ अपने स्वयं के पते के स्थान की अनुमति दे सकता है) अपने आप ही पता स्थान हो जाता है।

यह स्मृति प्रबंधन इकाई है कि शारीरिक वालों के लिए आभासी पते कैसे मैप (और पेज दोष जैसी चीजों को संभाल बदली पृष्ठों माध्यमिक भंडारण से में वापस खरीदा जा करने की आवश्यकता है) है।

निम्न आरेख मदद मिल सकती है, प्रत्येक अनुभाग स्मृति का एक 4K ब्लॉक का प्रतिनिधित्व:

Process A   Physical Memory  Process B 
    +-------+   +-------------+  +-------+ 
0K |  |----> 0K | (shared) | <----|  | 0K 
    +-------+   +-------------+  +-------+ 
4K |  |--+  4K |    | <----|  | 4K 
    +-------+ |  +-------------+  +-------+ 
8K |  | +-> 8K |    |  |  | 8K 
    +-------+   +-------------+  +-------+ 
     |    : : : : : : :   | 
     |    +-------------+   | 
     |   128K |    | <--------+ 
     |    +-------------+ 
     +--------> 132K |    | 
         +-------------+ 

आप देख सकते हैं, कि चित्र में, आभासी स्मृति पते और भौतिक स्मृति पते (और प्रक्रियाओं के लिए संभावना के बीच डिस्कनेक्ट मेमोरी ब्लॉक को भी साझा करने के लिए)। बाएं और दाहिने तरफ के पते आभासी पते हैं जो प्रक्रियाओं को देखते हैं।

केंद्रीय ब्लॉक में पतों वास्तविक भौतिक पते जहां डाटा "वास्तव में" है, और MMU मानचित्रण संभालती है।

fork (और exec) की गहरी व्याख्या के लिए, आप this answer पर भी देखना चाह सकते हैं।

+0

यह भी ध्यान दें कि इसे इस तरह से होना चाहिए। यदि 'y' का पता बदल गया है, तो कांटे से पहले चर या संरचनाओं में आयोजित किसी भी पॉइंटर्स (पते) कांटा के बाद सही नहीं होगा। इससे फोर्क बहुत कम उपयोगी होगा, क्योंकि बच्चे की प्रक्रिया किसी भी डेटा संरचनाओं (लिंक्ड सूचियों, पेड़ों) या गतिशील रूप से आवंटित डेटा तक पहुंचने में सक्षम नहीं होगी, क्योंकि ये चीजें पॉइंटर्स पर भरोसा करती हैं। वर्चुअल मेमोरी के बिना सिस्टम बहुत अधिक फोर्क लागू नहीं कर सकते हैं, आपको इसके बजाय vfork (http://pubs.opengroup.org/onlinepubs/7908799/xsh/vfork.html) मिलता है। –

+0

तकनीकी रूप से "इस तरह से नहीं होना चाहिए" - आप दोगुनी अप्रत्यक्ष पॉइंटर्स का उपयोग कर सकते हैं, बशर्ते आपके सी रनटाइम समर्थन दें (दूसरे शब्दों में, एक सूचक एक ज्ञात मान से ऑफसेट होता है, और जब फोर्किंग होता है, तो आप डेटा को कहीं और स्थानांतरित करते हैं बच्चे और ज्ञात मूल्य समायोजित करें)। हालांकि यह एक प्रदर्शन हत्यारा होगा। मुझे लगता है कि रीयल-मोड विंडोज ने स्मृति के लॉकिंग और अनलॉकिंग के साथ ऐसा कुछ किया था। – paxdiablo

+1

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

1

पता 'एक ही' है के रूप में प्रत्येक प्रक्रिया का अपना वर्चुअल ऐड्रेस स्पेस है और चर आम तौर पर एक ही स्थान में लोड किया जाएगा। ध्यान दें कि यह स्मृति में भौतिक पता नहीं है। यह भी ध्यान रखें कि ऐसी योजनाएं हैं जो जानबूझकर उस स्थान को यादृच्छिक रूप से याद करती हैं जिस पर प्रक्रिया को हमला करने/प्रक्रिया को कठिन बनाने के लिए प्रक्रिया को लोड किया जाता है। उस स्थिति में पता अलग होगा।