क्या प्रत्येक क्षेत्र आरेख में एक खंड है?
ये "सेगमेंट" शब्द के 2 लगभग पूरी तरह से अलग-अलग उपयोग हैं।
- x86 विभाजन / खंड रजिस्टर: आधुनिक x86 OS एक समतल मेमोरी मॉडल का उपयोग करते हैं, जहां सभी खंडों का आधार = 0 और सीमा = अधिकतम 32-बिट मोड में होता है, वही हार्डवेयर लागू करता है जो 64-बिट मोड में , विभाजन के प्रकार को क्रमिक बनाता है । (एफएस या जीएस को छोड़कर, थ्रेड-स्थानीय भंडारण के लिए 64-बिट मोड में भी उपयोग किया जाता है।)
- लिंकर / प्रोग्राम-लोडर सेक्शन / सेगमेंट। ( ईएलएफ फ़ाइल प्रारूप में अनुभाग और खंड का अंतर क्या है )
Usages की एक सामान्य उत्पत्ति है: यदि आप खंडित मेमोरी मॉडल (विशेष रूप से पृष्ठांकित वर्चुअल मेमोरी के बिना) का उपयोग कर रहे थे , तो आपके पास डेटा हो सकता है और बीएसएस पते डीएस सेगमेंट बेस के सापेक्ष हो सकते हैं, एसएस आधार के सापेक्ष ढेर हो सकते हैं, और कोड के सापेक्ष सीएस आधार पता।
तो कई अलग-अलग कार्यक्रमों को अलग-अलग रैखिक पतों में लोड किया जा सकता है, या यहां तक कि शुरू करने के बाद भी स्थानांतरित किया जा सकता है, खंड आधारों के सापेक्ष 16 या 32-बिट ऑफ़सेट को बदले बिना।
लेकिन फिर आपको यह जानना होगा कि सूचक किस खंड के सापेक्ष है, इसलिए आपके पास "बहुत दूर" और इतने पर हैं। (वास्तविक 16-बिट x86 प्रोग्राम को अक्सर अपने कोड को डेटा के रूप में एक्सेस करने की आवश्यकता नहीं होती है, इसलिए कहीं 64k कोड सेगमेंट का उपयोग कर सकता है, और शायद डीएस = एसएस के साथ एक और 64k ब्लॉक, उच्च ऑफसेट से नीचे बढ़ने के साथ, और डेटा पर। नीचे। या सभी खंड आधारों वाला एक छोटा कोड मॉडल)।
कैसे x86 विभाजन पेजिंग के साथ बातचीत करता है
32/64-बिट मोड में पता मानचित्रण है:
- सेगमेंट: ऑफ़सेट (सेगमेंट बेस जो आंसर को पकड़े हुए है, या एक निर्देश उपसर्ग के साथ ओवरराइड किया गया है)
- 32 या 64-बिट रैखिक आभासी पता = आधार + ऑफसेट। (लिनक्स जैसे फ्लैट मेमोरी मॉडल में, पॉइंटर्स / ऑफसेट = लीनियर एड्रेस भी। एफएस या जीएस के सापेक्ष टीएलएस को एक्सेस करते समय छोड़कर।)
पेज टेबल (टीएलबी द्वारा कैश किया गया) 32 (लीगेसी मोड), 36 (विरासत पीएई), या 52-बिट (x86-64) भौतिक पते के लिए रैखिक रेखांकन। ( /programming/46509152/why-in-64bit-the-virtual-address-are-4-bits-short-48bit-long-compared-with-the )।
यह चरण वैकल्पिक है: बूटिंग के दौरान नियंत्रण रजिस्टर में थोड़ी सी सेटिंग करके पेजिंग को सक्षम किया जाना है। पेजिंग के बिना, रैखिक पते भौतिक पते हैं।
ध्यान दें कि विभाजन आपको एक ही प्रक्रिया (या थ्रेड) में 32 या 64 बिट से अधिक वर्चुअल एड्रेस स्पेस का उपयोग करने की अनुमति नहीं देता है , क्योंकि फ्लैट (रैखिक) एड्रेस स्पेस में केवल मैप किए गए बिट्स की संख्या खुद ऑफसेट के रूप में होती है। (यह 16-बिट x 86 के लिए मामला नहीं था, जहां विभाजन वास्तव में 16-बिट रजिस्टरों और ऑफ़सेट्स के साथ 64k से अधिक मेमोरी का उपयोग करने के लिए उपयोगी था।)
सीपीयू कैश सेगमेंट डिस्क्रिप्टर को जीडीटी (या एलडीटी) से लोड करता है, जिसमें सेगमेंट बेस शामिल है। जब आप एक पॉइंटर को डिफाइन करते हैं, तो यह किस रजिस्टर पर निर्भर करता है, यह सेगमेंट के रूप में डीएस या एसएस के लिए डिफॉल्ट करता है। रजिस्टर वैल्यू (पॉइंटर) को सेगमेंट बेस से ऑफसेट के रूप में माना जाता है।
चूंकि सेगमेंट बेस सामान्य रूप से शून्य है, इसलिए सीपीयू विशेष-केस करते हैं। या किसी अन्य के नजरिए से, यदि आप ऐसा एक गैर शून्य खंड आधार है, भार अतिरिक्त विलंबता है, क्योंकि "विशेष" (सामान्य) जोड़ने आधार पते पर लागू नहीं होता को दरकिनार करने का मामला।
लिनक्स x86 सेगमेंट रजिस्टर को कैसे सेट करता है:
CS / DS / ES / SS का आधार और सीमा 32 में सभी 0 / -1 और 64-बिट मोड हैं। इसे फ्लैट मेमोरी मॉडल कहा जाता है क्योंकि सभी पॉइंटर्स एक ही एड्रेस स्पेस में जाते हैं।
(एएमडी सीपीयू आर्किटेक्ट्स ने 64-बिट मोड के लिए एक फ्लैट मेमोरी मॉडल लागू करके विभाजन को रोक दिया क्योंकि मुख्यधारा के OSes वैसे भी इसका उपयोग नहीं कर रहे थे, बिना किसी क्रियान्वयन संरक्षण के जो PAE या x86- के साथ पेजिंग करके बहुत बेहतर तरीके से प्रदान किया गया था- 64 पृष्ठ-तालिका प्रारूप।)
टीएलएस (थ्रेड लोकल स्टोरेज): एफएस और जीएस को लंबे मोड में आधार = 0 पर तय नहीं किया जाता है। (वे 386 के साथ नए थे, और किसी भी निर्देश द्वारा स्पष्ट रूप से उपयोग नहीं किए गए थे, rep
-स्ट्रिंग निर्देश भी नहीं जो ईएस का उपयोग करते हैं)। x86-64 लिनक्स टीएलएस ब्लॉक के पते पर प्रत्येक थ्रेड के लिए एफएस आधार पता सेट करता है।
उदाहरण के mov eax, [fs: 16]
लिए, इस धागे के लिए टीएलएस ब्लॉक में 16 बाइट्स से 32-बिट मान लोड करता है।
CS सेगमेंट डिस्क्रिप्टर चुनता है कि CPU किस मोड में है (16/32/64-बिट संरक्षित मोड / लॉन्ग मोड)। लिनक्स सभी 64-बिट उपयोगकर्ता-अंतरिक्ष प्रक्रियाओं के लिए एकल GDT प्रविष्टि का उपयोग करता है, और सभी 32-बिट उपयोगकर्ता-स्थान प्रक्रियाओं के लिए एक और GDT प्रविष्टि। (सही काम करने के लिए सीपीयू के लिए, डीएस / ईएस को भी मान्य प्रविष्टियों को सेट करना होगा, और इसी तरह एसएस)। यह विशेषाधिकार स्तर (कर्नेल (रिंग 0) बनाम उपयोगकर्ता (रिंग 3)) भी चुनता है, इसलिए 64-बिट उपयोगकर्ता-स्थान पर लौटने पर भी, कर्नेल को CS को सामान्य के बजाय बदलने, उपयोग करने iret
या व्यवस्थित करने की व्यवस्था करनी होती sysret
है) कूदना या हिदायत देना।
X86-64 में, syscall
प्रविष्टि बिंदु swapgs
उपयोगकर्ता-स्पेस के जीएस से कर्नेल के लिए जीएस फ्लिप करने के लिए उपयोग करता है, जिसका उपयोग वह इस थ्रेड के लिए कर्नेल स्टैक को खोजने के लिए करता है। (धागा-स्थानीय भंडारण का एक विशेष मामला)। syscall
अनुदेश गिरी ढेर पर बात करने के लिए ढेर सूचक परिवर्तन नहीं करता है; जब कर्नेल प्रवेश बिंदु 1 तक पहुँचता है तब भी यह उपयोगकर्ता के ढेर की ओर इशारा करता है ।
CPU / DS / ES / SS को भी संरक्षित मोड / लॉन्ग मोड में काम करने के लिए CPU के लिए मान्य सेगमेंट डिस्क्रिप्टर पर सेट करना होता है, भले ही उन डिस्क्रिप्टर से आधार / सीमा को लॉन्ग मोड में अनदेखा किया गया हो।
तो मूल रूप से x86 विभाजन का उपयोग TLS के लिए किया जाता है, और अनिवार्य x86 osdev सामान के लिए जिसे हार्डवेयर को करने की आवश्यकता होती है।
फुटनोट 1: मजेदार इतिहास: एएमडी 64 सिलिकॉन रिलीज होने से कुछ साल पहले कर्नेल देवों और एएमडी आर्किटेक्ट्स के बीच संदेशों की मेलिंग सूची अभिलेखागार हैं, जिसके परिणामस्वरूप डिजाइन करने के लिए टीकियों syscall
का उपयोग किया गया था। विवरण के लिए इस उत्तर में लिंक देखें ।