2012-06-05 14 views
5

का उपयोग करते हैं, मैं समझने की कोशिश कर रहा हूं कि स्मृति प्रबंधन निम्न स्तर पर कैसे चलता है और कुछ प्रश्न हैं।सेगमेंटेशन रजिस्ट्रार

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

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

3) ऑपरेटिंग सिस्टम जो सेगमेंटेशन प्रोग्राम को लॉजिकल सेगमेंट में विभाजित नहीं करते हैं? उदाहरण के लिए, वे सेगमेंट डिस्क्रिप्टर के बिना कोड से स्टैक को कैसे अलग करते हैं। मैंने पढ़ा है कि ऐसी चीजों को संभालने के लिए पेजिंग का उपयोग किया जा सकता है, लेकिन यह समझ में नहीं आता कि कैसे।

उत्तर

3

Benoit's answer to question 3 पर विस्तार ...

ऐसे तार्किक भागों में कार्यक्रमों का विभाजन कोड, निरंतर डेटा, संशोधित डेटा और स्टैक अलग-अलग एजेंटों द्वारा समय पर अलग-अलग बिंदुओं पर किया जाता है।

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

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

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

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

यदि ओएस में डेटा मेमोरी से कोड मेमोरी को अलग करने या मेमोरी एक्सेस अधिकारों को लागू करने के लिए कोई हार्डवेयर या कोड नहीं है, तो विभाजन बहुत औपचारिक है। 16-बिट रीयल-मोड डॉस प्रोग्राम्स (COM और EXE) में कुछ विशेष तरीके से चिह्नित कोड, डेटा और स्टैक सेगमेंट नहीं थे। COM कार्यक्रमों में सब कुछ एक सामान्य 64 केबी सेगमेंट में था और उन्होंने आईपी = 0x100 और एसपी = 0xFFxx के साथ शुरू किया और कोड और डेटा का क्रम मनमाने ढंग से अंदर हो सकता है, वे व्यावहारिक रूप से स्वतंत्र रूप से intertwine सकता है। डॉस EXE फ़ाइलों ने केवल प्रारंभिक सीएस निर्दिष्ट किया: आईपी और एसएस: एसपी स्थान और इससे परे कि कोड, डेटा और स्टैक सेगमेंट डॉस के लिए अलग-अलग थे। इसे करने की आवश्यकता है फ़ाइल को लोड करना, स्थानांतरण करना (केवल EXEs के लिए), पीएसपी (प्रोग्राम सेगमेंट उपसर्ग, जिसमें कमांड लाइन पैरामीटर और कुछ अन्य नियंत्रण जानकारी शामिल है) सेट करें, एसएस: एसपी और सीएस: आईपी लोड करें।यह स्मृति की रक्षा नहीं कर सका क्योंकि वास्तविक सुरक्षा मोड में स्मृति सुरक्षा उपलब्ध नहीं है, और इसलिए 16-बिट डॉस निष्पादन योग्य प्रारूप बहुत ही सरल थे।

+0

महान जवाब, धन्यवाद! –

+0

@AntonFrolov यदि आपके प्रश्न का उत्तर दिया गया है, तो सबसे अच्छा जवाब स्वीकार करने के लिए मत भूलना। –

-1

विकिपीडिया इस मामले में आपका मित्र है। http://en.wikipedia.org/wiki/Memory_segmentation और http://en.wikipedia.org/wiki/X86_memory_segmentation अच्छे शुरुआती बिंदु होना चाहिए।

मुझे यकीन है कि यहां अन्य लोग हैं जो व्यक्तिगत रूप से गहराई से स्पष्टीकरण प्रदान कर सकते हैं।

4
  1. आप अब और वास्तविक-मोड ;-) के लिए वास्तव में कुछ पुरानी किताबें क्योंकि कोई भी कार्यक्रम को पढ़ लिया है चाहिए वास्तविक-मोड में, आप phyical address = segment register * 0x10 + offset के साथ एक स्मृति पहुँच का भौतिक पता प्राप्त कर सकते हैं, ऑफसेट सामान्य प्रयोजन रजिस्टरों में से एक के अंदर एक मूल्य होने के नाते। चूंकि ये रजिस्ट्रार 16 बिट चौड़े हैं, इसलिए एक सेगमेंट 64kb लंबा होगा और इसके आकार के बारे में आप कुछ भी नहीं कर सकते हैं, सिर्फ इसलिए कि कोई विशेषता नहीं है! * 0x10 गुणा के साथ, 1 एमबी मेमोरी उपलब्ध हो जाती है, लेकिन सेगमेंट रजिस्ट्रार और पता रजिस्टर पर आपके द्वारा रखे गए कार्यों के आधार पर ओवरलैपिंग संयोजन होते हैं। मैंने रीयल-मोड के लिए कोई कोड संकलित नहीं किया है, लेकिन मुझे लगता है कि बाइनरी लोडिंग के दौरान सेगमेंट रजिस्ट्रार सेट करने के लिए ओएस तक है, जैसे कि लोडर ईएलएफ बाइनरी लोड करते समय कुछ पेज आवंटित करेगा। हालांकि मैंने नंगे धातु कर्नेल कोड संकलित किया है, और मुझे इन रजिस्टरों को स्वयं ही स्थापित करना था।

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

  3. मेरे पास गंभीर ओएस का कोई उदाहरण नहीं है जो विभाजन का कोई उपयोग करता है, सिर्फ इसलिए कि पिछड़ा अनुपालन के लिए विभाजन अभी भी मौजूद है। फ्लैट मॉडल दृष्टिकोण का उपयोग करना इससे छुटकारा पाने के लिए कुछ भी नहीं है। वैसे भी, आप सही हैं, पेजिंग अधिक कुशल और बहुमुखी है, और लगभग सभी वास्तुकला (कम से कम अवधारणाओं) पर उपलब्ध है। मैं यहाँ व्याख्या नहीं कर सकते internals पेजिंग, लेकिन सभी जानकारी आप जानना चाहते हैं उत्कृष्ट इंटेल आदमी के अंदर कर रहे हैं: Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide, Part 1

+0

हम्म, 1) तो बाइनरी लोड होने पर सेगमेंट रजिस्ट्रार स्थापित किए जाते हैं? लेकिन क्या होगा यदि कोई ओएस नहीं है और हम कच्चे हार्डवेयर के साथ काम कर रहे हैं, उदा। अगर मैं बीआईओएस की तरह कुछ लिखता हूं। 2) अगर मैं सही ढंग से समझता हूं, तो हार्डवेयर स्तर पर विशेषाधिकार स्विच करने में सक्षम होने के लिए कर्नेल और उपयोगकर्ता स्पेस के लिए सेगमेंट की आवश्यकता होती है। लेकिन मुझे समझ में नहीं आता कि डेटा और कोड के लिए अलग-अलग सेगमेंट क्यों जरूरी हैं। उदाहरण के लिए, क्या होता है यदि दोनों सीएस और डीएस रजिस्ट्रार जीडीटी में एक ही प्रविष्टि को इंगित करेंगे। –

+0

1) नंगे धातु पर, आपको 'mov' निर्देशों के साथ 'ljmp' निर्देश और डीएस, ईएस, एफएस, जीएस के साथ मैन्युअल रूप से सीएस लोड करना होगा। आपके कार्यक्रम की शुरुआत में शुरुआत की जानी है। 2) क्योंकि _segment descriptor_ descripts या तो कोड या डेटा सेगमेंट है, लेकिन एक कोड + डेटा सेगमेंट, आपको कोड सेगमेंट और डेटा सेगमेंट के लिए _ सेगमेंट डिस्क्रिप्टर_ सेट करना होगा। – Benoit

+2

'रीयल-मोड के लिए अब कोई भी प्रोग्राम नहीं है' एक ओवरस्टेटमेंट है। :) –

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