जब कंप्यूटर प्रोग्राम चलता है तो क्या होता है?


180

मैं सामान्य सिद्धांत जानता हूं, लेकिन मैं विवरण में फिट नहीं हो सकता।

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

मुझे यह भी पता है कि एक कंप्यूटर प्रोग्राम दो प्रकार की मेमोरी का उपयोग करता है: स्टैक और हीप, जो कंप्यूटर की प्राथमिक मेमोरी का भी हिस्सा हैं। स्टैक का उपयोग गैर-गतिशील मेमोरी के लिए किया जाता है, और डायनेमिक मेमोरी के लिए ढेर (उदाहरण के लिए, newC ++ में ऑपरेटर से संबंधित सब कुछ )

मुझे समझ नहीं आ रहा है कि वे दो चीजें कैसे जुड़ती हैं। निर्देशों के निष्पादन के लिए किस बिंदु पर स्टैक का उपयोग किया जाता है? निर्देश रैम से, स्टैक तक, रजिस्टरों में जाते हैं?


43
एक मौलिक सवाल पूछने के लिए +1!
mkelley33

21
हम्म ... तुम्हें पता है, वे उस बारे में किताबें लिखते हैं। क्या आप वास्तव में एसओ की मदद से ओएस आर्किटेक्चर के इस हिस्से का अध्ययन करना चाहते हैं?
एंड्री

1
मैंने सवाल के मेमोरी-संबंधित प्रकृति और सी ++ के संदर्भ के आधार पर कुछ टैग जोड़े, हालांकि मुझे लगता है कि जावा या सी # में किसी जानकार का एक अच्छा जवाब भी आ सकता है!
mkelley33

14
उत्कीर्ण और इष्ट। मैं हमेशा पूछने से डरता रहा हूं ...
मैक्सएम

2
शब्द "उन्हें रजिस्टर में रखता है" काफी सही नहीं है। अधिकांश प्रोसेसर पर, रजिस्टरों का उपयोग मध्यवर्ती मूल्यों को रखने के लिए किया जाता है, निष्पादन योग्य कोड पर नहीं।

जवाबों:


161

यह वास्तव में सिस्टम पर निर्भर करता है, लेकिन वर्चुअल मेमोरी वाले आधुनिक ओएस अपनी प्रक्रिया छवियों को लोड करते हैं और मेमोरी को कुछ इस तरह आवंटित करते हैं:

+---------+
|  stack  |  function-local variables, return addresses, return values, etc.
|         |  often grows downward, commonly accessed via "push" and "pop" (but can be
|         |  accessed randomly, as well; disassemble a program to see)
+---------+
| shared  |  mapped shared libraries (C libraries, math libs, etc.)
|  libs   |
+---------+
|  hole   |  unused memory allocated between the heap and stack "chunks", spans the
|         |  difference between your max and min memory, minus the other totals
+---------+
|  heap   |  dynamic, random-access storage, allocated with 'malloc' and the like.
+---------+
|   bss   |  Uninitialized global variables; must be in read-write memory area
+---------+
|  data   |  data segment, for globals and static variables that are initialized
|         |  (can further be split up into read-only and read-write areas, with
|         |  read-only areas being stored elsewhere in ROM on some systems)
+---------+
|  text   |  program code, this is the actual executable code that is running.
+---------+

यह कई सामान्य वर्चुअल-मेमोरी सिस्टम पर सामान्य प्रक्रिया पता स्थान है। "छेद" आपकी कुल मेमोरी का आकार है, जो अन्य सभी क्षेत्रों द्वारा उठाए गए स्थान को घटाता है; यह ढेर को बढ़ने के लिए बड़ी मात्रा में जगह देता है। यह "वर्चुअल" भी है, जिसका अर्थ है कि यह अनुवाद तालिका के माध्यम से आपकी वास्तविक मेमोरी में मैप करता है , और वास्तव में वास्तविक मेमोरी में किसी भी स्थान पर संग्रहीत किया जा सकता है। यह एक प्रक्रिया को किसी अन्य प्रक्रिया की मेमोरी तक पहुंचने से बचाने के लिए किया जाता है, और प्रत्येक प्रक्रिया को लगता है कि यह एक संपूर्ण सिस्टम पर चल रहा है।

ध्यान दें कि, की स्थिति, जैसे, ढेर और ढेर कुछ प्रणालियों पर एक अलग क्रम में हो सकते हैं ( बिली ओ'नील का जवाब देखें) Win32 पर अधिक जानकारी के लिए नीचे देखें)।

अन्य प्रणालियाँ बहुत भिन्न हो सकती हैं । उदाहरण के लिए, DOS वास्तविक मोड में चलता है , और प्रोग्राम चलाने के दौरान इसका मेमोरी आवंटन बहुत अलग दिखता है:

+-----------+ top of memory
| extended  | above the high memory area, and up to your total memory; needed drivers to
|           | be able to access it.
+-----------+ 0x110000
|  high     | just over 1MB->1MB+64KB, used by 286s and above.
+-----------+ 0x100000
|  upper    | upper memory area, from 640kb->1MB, had mapped memory for video devices, the
|           | DOS "transient" area, etc. some was often free, and could be used for drivers
+-----------+ 0xA0000
| USER PROC | user process address space, from the end of DOS up to 640KB
+-----------+
|command.com| DOS command interpreter
+-----------+ 
|    DOS    | DOS permanent area, kept as small as possible, provided routines for display,
|  kernel   | *basic* hardware access, etc.
+-----------+ 0x600
| BIOS data | BIOS data area, contained simple hardware descriptions, etc.
+-----------+ 0x400
| interrupt | the interrupt vector table, starting from 0 and going to 1k, contained 
|  vector   | the addresses of routines called when interrupts occurred.  e.g.
|  table    | interrupt 0x21 checked the address at 0x21*4 and far-jumped to that 
|           | location to service the interrupt.
+-----------+ 0x0

आप देख सकते हैं कि डॉस ने बिना किसी सुरक्षा के साथ ऑपरेटिंग सिस्टम मेमोरी तक सीधे पहुंच की अनुमति दी, जिसका अर्थ था कि उपयोगकर्ता-अंतरिक्ष कार्यक्रम आम तौर पर सीधे पहुंच सकते हैं या किसी भी चीज़ को अधिलेखित कर सकते हैं जो उन्हें पसंद है।

प्रोसेस एड्रेस स्पेस में, हालांकि, प्रोग्राम समान दिखने के लिए थे, केवल उन्हें कोड सेगमेंट, डेटा सेगमेंट, हीप, स्टैक सेगमेंट, आदि के रूप में वर्णित किया गया था, और इसे थोड़ा अलग तरीके से मैप किया गया था। लेकिन अधिकांश सामान्य क्षेत्र अभी भी थे।

प्रोग्राम को लोड करने और मेमोरी में आवश्यक साझा करने पर, और प्रोग्राम के हिस्सों को सही क्षेत्रों में वितरित करने पर, ओएस आपकी प्रक्रिया को क्रियान्वित करना शुरू कर देता है जहां भी इसकी मुख्य विधि होती है, और आपका प्रोग्राम वहां से शुरू होता है, जब आवश्यक हो तो सिस्टम कॉल करना यह उनकी जरूरत है।

विभिन्न प्रणालियों (एम्बेडेड, जो भी हो) में बहुत अलग आर्किटेक्चर हो सकते हैं, जैसे स्टैकलेस सिस्टम, हार्वर्ड आर्किटेक्चर सिस्टम (कोड और डेटा को अलग-अलग भौतिक मेमोरी में रखा जा रहा है), सिस्टम जो वास्तव में बीएसएस को केवल-पढ़ने योग्य मेमोरी में रखते हैं (शुरू में सेट द्वारा प्रोग्रामर), आदि। लेकिन यह सामान्य है।


तुमने कहा था:

मुझे यह भी पता है कि एक कंप्यूटर प्रोग्राम दो प्रकार की मेमोरी का उपयोग करता है: स्टैक और हीप, जो कंप्यूटर की प्राथमिक मेमोरी का भी हिस्सा हैं।

"स्टैक" और "हीप" स्मृति के बजाय (आवश्यक) शारीरिक रूप से अलग "प्रकार" के बजाय केवल अमूर्त अवधारणाएं हैं।

एक ढेर केवल एक अंतिम-इन, पहली-आउट डेटा संरचना है। X86 आर्किटेक्चर में, इसे वास्तव में अंत से एक ऑफसेट का उपयोग करके यादृच्छिक रूप से संबोधित किया जा सकता है, लेकिन इसमें से आइटम जोड़ने और हटाने के लिए सबसे आम कार्य PUSH और POP हैं। यह आमतौर पर फ़ंक्शन-स्थानीय चर (तथाकथित "स्वचालित भंडारण"), फ़ंक्शन तर्क, रिटर्न पते आदि (अधिक नीचे) के लिए उपयोग किया जाता है

एक "हीप" स्मृति के एक टुकड़े के लिए एक उपनाम है जिसे मांग पर आवंटित किया जा सकता है, और यादृच्छिक रूप से संबोधित किया जाता है (मतलब, आप इसमें किसी भी स्थान तक सीधे पहुंच सकते हैं)। यह आमतौर पर डेटा संरचनाओं के लिए उपयोग किया जाता है जो आप रनटाइम पर आवंटित करते हैं (सी ++ में, उपयोग newऔर delete, औरmalloc सी में दोस्तों, आदि)।

स्टैक और हीप, x86 आर्किटेक्चर पर, दोनों आपके सिस्टम मेमोरी (RAM) में भौतिक रूप से निवास करते हैं, और वर्चुअल मेमोरी आवंटन के माध्यम से ऊपर बताए गए प्रोसेस एड्रेस स्पेस में मैप किए जाते हैं।

रजिस्टरों (अभी भी 86 पर), शारीरिक रूप से प्रोसेसर (के रूप में राम के खिलाफ) के अंदर रहते हैं, और पाठ क्षेत्र से, प्रोसेसर के द्वारा लोड किए गए हैं (और यह भी स्मृति या अन्य स्थानों में कहीं और से लोड किया जा सकता सीपीयू निर्देश पर निर्भर करता है कि वास्तव में क्रियान्वित होते हैं)। वे अनिवार्य रूप से बहुत छोटे, बहुत तेज़ ऑन-चिप मेमोरी लोकेशन हैं जो कई अलग-अलग उद्देश्यों के लिए उपयोग किए जाते हैं।

रजिस्टर लेआउट आर्किटेक्चर पर अत्यधिक निर्भर है (वास्तव में, रजिस्टर, इंस्ट्रक्शन सेट, और मेमोरी लेआउट / डिज़ाइन, वास्तव में "आर्किटेक्चर" से क्या अभिप्राय है), और इसलिए मैं इस पर विस्तार नहीं करूंगा, लेकिन आपको लेने की सलाह देता हूं उन्हें बेहतर समझने के लिए असेंबली लैंग्वेज कोर्स।


आपका प्रश्न:

निर्देशों के निष्पादन के लिए किस बिंदु पर स्टैक का उपयोग किया जाता है? निर्देश रैम से, स्टैक तक, रजिस्टरों में जाते हैं?

स्टैक (सिस्टम / भाषाओं में जो उनके पास हैं और उनका उपयोग करते हैं) को अक्सर इस तरह से उपयोग किया जाता है:

int mul( int x, int y ) {
    return x * y;       // this stores the result of MULtiplying the two variables 
                        // from the stack into the return value address previously 
                        // allocated, then issues a RET, which resets the stack frame
                        // based on the arg list, and returns to the address set by
                        // the CALLer.
}

int main() {
    int x = 2, y = 3;   // these variables are stored on the stack
    mul( x, y );        // this pushes y onto the stack, then x, then a return address,
                        // allocates space on the stack for a return value, 
                        // then issues an assembly CALL instruction.
}

इस तरह एक सरल कार्यक्रम लिखें, और फिर इसे विधानसभा ( gcc -S foo.cयदि आपके पास जीसीसी तक पहुंच है) के लिए संकलित करें, और एक नज़र डालें। असेंबली का पालन करना बहुत आसान है। आप देख सकते हैं कि स्टैक का उपयोग फंक्शन लोकल वेरिएबल के लिए किया जाता है, और कॉलिंग फंक्शन्स के लिए, उनके तर्कों और रिटर्न वैल्यूज़ को स्टोर करने के लिए। ऐसा इसलिए भी है क्योंकि जब आप कुछ ऐसा करते हैं:

f( g( h( i ) ) ); 

इन सभी को बदले में बुलाया जाता है। यह वस्तुतः फ़ंक्शन कॉल और उनके तर्कों का एक ढेर बना रहा है, उन्हें क्रियान्वित कर रहा है, और फिर उन्हें बंद कर देता है क्योंकि यह वापस नीचे (या ऊपर) हवाएं होती हैं। हालांकि, जैसा कि ऊपर उल्लेख किया गया है, स्टैक (x86 पर) वास्तव में आपकी प्रक्रिया मेमोरी स्पेस (आभासी मेमोरी में) में रहता है, और इसलिए इसे सीधे हेरफेर किया जा सकता है; यह निष्पादन के दौरान एक अलग कदम नहीं है (या कम से कम प्रक्रिया के लिए रूढ़िवादी है)।

FYI करें, उपरोक्त C कॉलिंग कन्वेंशन है , जिसका उपयोग C ++ द्वारा भी किया जाता है। अन्य भाषाएँ / सिस्टम एक अलग क्रम में स्टैक पर तर्कों को धक्का दे सकते हैं, और कुछ भाषाएँ / प्लेटफ़ॉर्म भी स्टैक का उपयोग नहीं करते हैं, और इसके बारे में विभिन्न तरीकों से चलते हैं।

यह भी ध्यान दें, ये C कोड निष्पादन की वास्तविक रेखाएँ नहीं हैं। संकलक ने उन्हें आपके निष्पादन योग्य में मशीन भाषा निर्देशों में परिवर्तित कर दिया है। तब उन्हें (आम तौर पर) TEXT क्षेत्र से CPU पाइपलाइन में कॉपी किया जाता है, फिर CPU रजिस्टरों में, और वहां से निष्पादित किया जाता है। [यह गलत था। देखें बेन वोइट के सुधार नीचे।]


4
क्षमा करें, लेकिन एक अच्छी पुस्तक की सिफारिश एक बेहतर जवाब होगा, IMO
एंड्री

13
हाँ, "RTFM" हमेशा बेहतर होता है।
Sdaz MacSkibbons

56
@ भारत: शायद आपको उस टिप्पणी को बदल देना चाहिए "यह भी, आप अपनी अच्छी-किताब-सिफारिश पढ़ना चाहते हैं " मैं समझता हूं कि इस तरह का प्रश्न अधिक जांच-पड़ताल करता है, लेकिन जब भी आपको "खेद" के साथ एक टिप्पणी शुरू करनी होगी। .. "शायद आपको मध्यस्थ ध्यान के लिए पोस्ट को फ़्लैग करने या कम से कम एक स्पष्टीकरण देने के बारे में विचार करना चाहिए कि आपकी राय वैसे भी किसी के लिए क्या होनी चाहिए।
mkelley33

2
बहुत बढ़िया जवाब। यह निश्चित रूप से मेरे लिए कुछ चीजों को मंजूरी दे दी!
शाम

2
@ मायिक: कार्यान्वयन के आधार पर, आपके पास अनिवार्य कैशिंग हो सकता है, जिस स्थिति में किसी भी समय डेटा को मेमोरी से पढ़ा जाता है, एक पूरी कैश लाइन पढ़ी जाती है और कैश पॉपुलेटेड होता है। या कैश मैनेजर को यह संकेत देना संभव हो सकता है कि डेटा की केवल एक बार जरूरत होगी, इसलिए इसे कैश में कॉपी करना मददगार नहीं है। वह पढ़ने के लिए है। लिखने के लिए राइट-बैक और राइट-थ्रू कैश हैं, जो तब प्रभावित होते हैं जब डीएमए कंट्रोलर डेटा पढ़ सकते हैं, और फिर कैश प्रोसेसर के एक पूरे मेजबान के लिए कई प्रोसेसर होते हैं, जिनमें से प्रत्येक का अपना कैश होता है। यह वास्तव में अपने क्यू के हकदार हैं
बेन वोइगट

61

Sdaz ने बहुत ही कम समय में एक उल्लेखनीय संख्या में वृद्धि प्राप्त की है, लेकिन दुर्भाग्य से सीपीयू के माध्यम से निर्देश कैसे आगे बढ़ते हैं, इस बारे में गलत धारणा है।

पूछे गए सवाल:

निर्देश रैम से, स्टैक तक, रजिस्टरों में जाते हैं?

Sdaz ने कहा:

यह भी ध्यान दें, ये C कोड निष्पादन की वास्तविक रेखाएँ नहीं हैं। संकलक ने उन्हें आपके निष्पादन योग्य में मशीन भाषा निर्देशों में परिवर्तित कर दिया है। तब उन्हें (आम तौर पर) TEXT क्षेत्र से CPU पाइपलाइन में कॉपी किया जाता है, फिर CPU रजिस्टरों में, और वहां से निष्पादित किया जाता है।

लेकिन यह गलत है। स्व-संशोधित कोड के विशेष मामले को छोड़कर, निर्देश कभी भी डाटापेट में नहीं आते हैं। और वे दत्तपथ से निष्पादित नहीं किए जा सकते हैं।

86 CPU रजिस्टरों हैं:

  • सामान्य रजिस्टर EAX EBX ECX EDX

  • खंड सीएस सीएस ईएस एफएस जीएस एसएस को पंजीकृत करता है

  • सूचकांक और संकेत ईएसआई ईडीआई ईबीपी ईईपी ईएसपी

  • संकेतक EFLAGS

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

इनमें से कोई भी रजिस्टर निष्पादन योग्य कोड के लिए उपयोग नहीं किया जाता है। EIPनिष्पादन निर्देश का पता है, न कि निर्देश ही।

निर्देश डेटा (हार्वर्ड आर्किटेक्चर) से सीपीयू में पूरी तरह से अलग रास्ते से गुजरते हैं। सभी मौजूदा मशीनें सीपीयू के अंदर हार्वर्ड आर्किटेक्चर हैं। इन दिनों अधिकांश कैश में हार्वर्ड आर्किटेक्चर भी हैं। x86 (आपकी सामान्य डेस्कटॉप मशीन) मुख्य मेमोरी में वॉन न्यूमैन आर्किटेक्चर हैं, जिसका अर्थ है कि डेटा और कोड रैम में परस्पर जुड़े हुए हैं। इस बिंदु के बगल में, चूंकि हम सीपीयू के अंदर क्या होता है, इसके बारे में बात कर रहे हैं।

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

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

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

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


स्पष्टीकरण के लिए धन्यवाद। मैं इसे जोड़ने में संकोच कर रहा था कि जैसा कि मैं इसके साथ परिचित नहीं हूं, लेकिन किसी और के अनुरोध पर ऐसा किया।
Sdaz MacSkibbons

s / ARM / RAM / "अर्थ डेटा और कोड ARM में परस्पर जुड़े हुए हैं"। सही?
बजर्के फ्रायंड-हैन्सन

@bjarkef: पहली बार हाँ, लेकिन दूसरी नहीं। मैं इसे ठीक कर दूंगा।
बेन वोइगट

17

किसी प्रक्रिया को निष्पादित करते समय मेमोरी का सटीक लेआउट पूरी तरह से उस प्लेटफॉर्म पर निर्भर करता है जिसका आप उपयोग कर रहे हैं। निम्नलिखित परीक्षण कार्यक्रम पर विचार करें:

#include <stdlib.h>
#include <stdio.h>

int main()
{
    int stackValue = 0;
    int *addressOnStack = &stackValue;
    int *addressOnHeap = malloc(sizeof(int));
    if (addressOnStack > addressOnHeap)
    {
        puts("The stack is above the heap.");
    }
    else
    {
        puts("The heap is above the stack.");
    }
}

Windows NT (और यह बच्चे हैं) पर, यह कार्यक्रम आम तौर पर उत्पादन करने जा रहा है:

ढेर ढेर के ऊपर है

POSIX बॉक्स पर, यह कहने जा रहा है:

ढेर ढेर के ऊपर है

UNIX मैमोरी मॉडल को यहाँ @Sdaz MacSkibbons द्वारा काफी अच्छी तरह से समझाया गया है, इसलिए मैं इसे यहाँ नहीं दोहराऊँगा। लेकिन वह केवल मेमोरी मॉडल नहीं है। POSIX के कारण इस मॉडल को sbrk सिस्टम कॉल की आवश्यकता होती है। मूल रूप से, POSIX बॉक्स पर, अधिक मेमोरी प्राप्त करने के लिए, एक प्रक्रिया केवल कर्नेल को "छेद" और "ढेर" के बीच "छेद" क्षेत्र में ले जाने के लिए कहती है। ऑपरेटिंग सिस्टम में मेमोरी को वापस करने का कोई तरीका नहीं है, और ऑपरेटिंग सिस्टम ही आपके ढेर का प्रबंधन नहीं करता है। आपके C रनटाइम लाइब्रेरी को (मालॉक के माध्यम से) प्रदान करना होगा।

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

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

विंडोज पर, वर्चुअल मेमोरी को सिस्टम से VirtualAlloc के लिए कॉल के माध्यम से प्राप्त किया जाता है , और इसे सिस्टम में VirtualFree (ठीक है, तकनीकी रूप से VirtualAlloc के माध्यम से NtAllocateVirtualMemory तक पहुँचाया जाता है, लेकिन यह एक कार्यान्वयन विवरण है) पुनः प्राप्त किया जाए)। यह प्रक्रिया धीमी है (और IIRC, के लिए आवश्यक है कि आप भौतिक पृष्ठ आकार के हिस्से में आवंटित करें; आमतौर पर 4kb या अधिक)। Windows यह भी प्रदान करता है कि वह स्वयं ही कार्य करता है (HeapAlloc, HeapFree, आदि) RtlHeap नामक एक लाइब्रेरी के हिस्से के रूप में, जो कि विंडोज के ही एक भाग के रूप में शामिल है, जिस पर C रनटाइम ( mallocऔर मित्रों और मित्रों) को आमतौर पर लागू किया जाता है।

विंडोज़ के पास उन दिनों से काफी विरासत मेमोरी आवंटन एपीआई है जब उसे पुराने 80386 से निपटना था, और ये कार्य अब RtlHeap के शीर्ष पर बने हैं। Windows में मेमोरी प्रबंधन को नियंत्रित करने वाले विभिन्न एपीआई के बारे में अधिक जानकारी के लिए, इस MSDN लेख को देखें: http://msdn.microsoft.com/en-us/library/ms810627

यह भी ध्यान दें कि इसका मतलब विंडोज पर एक एकल प्रक्रिया (और आमतौर पर) एक से अधिक ढेर है। (आमतौर पर, प्रत्येक साझा लाइब्रेरी खुद का ढेर बनाती है।)

(इस जानकारी के अधिकांश रॉबर्ट सीकॉर्ड द्वारा "सी और सी ++ में सुरक्षित कोडिंग" से आता है)


बढ़िया जानकारी, धन्यवाद! आशा है कि "user487117" वास्तव में वापस आता है। :-)
Sdaz MacSkibbons

5

ढेर

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

उदाहरण के लिए एक पूर्णांक गुणन:

MUL BX

गुणक AX BX रजिस्टर के साथ रजिस्टर करता है। (परिणाम DX और AX, DX में होगा जिसमें उच्च बिट्स होंगे)।

स्टैक आधारित मशीनें (जेएवीए वीएम की तरह) अपने मूल संचालन के लिए स्टैक का उपयोग करती हैं। उपरोक्त गुणन:

DMUL

यह स्टैक के शीर्ष से दो मूल्यों को पॉप करता है और मंदिरों को गुणा करता है, फिर परिणाम को स्टैक पर वापस धकेलता है। इस तरह की मशीनों के लिए स्टैक आवश्यक है।

कुछ उच्च स्तर की प्रोग्रामिंग भाषाएं (जैसे सी और पास्कल) फ़ंक्शन के मापदंडों को पारित करने के लिए इस बाद की विधि का उपयोग करती हैं: पैरामीटर को बाएं से दाएं क्रम में धकेल दिया जाता है और फ़ंक्शन बॉडी द्वारा पॉपअप किया जाता है और रिटर्न मान वापस धकेल दिए जाते हैं। (यह एक विकल्प है जो संकलक निर्माता बनाते हैं और जिस तरह से एक्स 86 स्टैक का उपयोग करते हैं उस तरह की गालियां देते हैं)।

ढेर

ढेर एक अन्य अवधारणा है जो केवल संकलक के दायरे में मौजूद है। यह स्मृति को अपने चरों के पीछे ले जाने की पीड़ा को दूर ले जाता है, लेकिन यह सीपीयू या ओएस का कार्य नहीं है, यह सिर्फ घर की रखवाली का एक विकल्प है कि मेमोरी ब्लॉक वाइच ओएस द्वारा दिया जाता है। यदि आप चाहें तो आप ऐसा कई बार कर सकते हैं।

सिस्टम संसाधनों तक पहुँचना

ऑपरेटिंग सिस्टम में एक सार्वजनिक इंटरफ़ेस है कि आप इसके कार्यों को कैसे एक्सेस कर सकते हैं। सीपीयू के रजिस्टरों में डॉस पैरामीटर पारित किए जाते हैं। विंडोज़ ओएस फ़ंक्शंस (विंडोज एपीआई) के लिए पैरामीटर पारित करने के लिए स्टैक का उपयोग करता है।

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