X86 पेजिंग कैसे काम करता है?




paging virtual-memory (2)

यहां एक बहुत छोटा, उच्च स्तरीय उत्तर है:

एक x86 प्रोसेसर कई संभावित तरीकों में से एक में काम करता है (लगभग: वास्तविक, संरक्षित, 64-बिट)। प्रत्येक मोड कई संभावित मेमोरी एड्रेसिंग मॉडलों में से एक का उपयोग कर सकता है (लेकिन हर मोड हर मॉडल का उपयोग नहीं कर सकता), अर्थात्: रीयल-मोड एड्रेसिंग, सेगमेंट एड्रेसिंग, और फ्लैट-रैखिक एड्रेसिंग।

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

अब, मेमोरी एड्रेसिंग मोड मशीन निर्देशों के मेमोरी ऑपरेंड (जैसे कि mov DWORD PTR [eax], 25 , जो mov DWORD PTR [eax], 25 -बिट (उर्फ dword ) को 25 की स्मृति में पूर्णांक में संग्रहीत करता है, जिसका स्मृति उस पते में संग्रहीत होता है जिसमें उसका पता संग्रहीत होता है eax 32-बिट रजिस्टर)। फ्लैट-रेखीय एड्रेसिंग में, eax में यह संख्या शून्य, अधिकतम मूल्य से (एक मामले में 2 32 - 1) तक, एकल, संगत रेंज पर चलाने की अनुमति है।

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

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

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

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

यह सवाल विषय पर अच्छी जानकारी के निर्वात को भरने के लिए है।

मेरा मानना ​​है कि एक अच्छा जवाब एक बड़े SO उत्तर में या कम से कम कुछ उत्तरों में फिट होगा।

मुख्य लक्ष्य पूर्ण शुरुआती लोगों को पर्याप्त जानकारी देना है ताकि वे मैन्युअल रूप से मैन्युअल रूप से ले सकें और पेजिंग से संबंधित मूल ओएस अवधारणाओं को समझ सकें।

सुझाए गए दिशानिर्देश:

  • जवाब शुरुआती दोस्ताना होना चाहिए:
    • ठोस, लेकिन संभवतः सरलीकृत उदाहरण बहुत महत्वपूर्ण हैं
    • दिखाए गए अवधारणाओं के अनुप्रयोगों का स्वागत है
  • उपयोगी संसाधनों का हवाला देना अच्छा है
  • ओएसएस पेजिंग सुविधाओं का उपयोग करने के तरीके में छोटे digressions स्वागत है
  • पीएई और पीएसई स्पष्टीकरण का स्वागत है
  • x86_64 में छोटे digressions स्वागत है

संबंधित प्रश्न और मुझे क्यों लगता है कि वे नकल नहीं हैं:


एक अच्छा टीओसी और अधिक सामग्री के साथ इस जवाब का संस्करण

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

नमूना कोड

न्यूनतम उदाहरण: https://github.com/cirosantilli/x86-bare-metal-examples/blob/5c672f73884a487414b3e21bd9e579c67cd77621/paging.S

प्रोग्रामिंग में सबकुछ की तरह, वास्तव में इसे समझने का एकमात्र तरीका न्यूनतम उदाहरणों के साथ खेलना है।

यह एक "कठिन" विषय बनाता है कि न्यूनतम उदाहरण बड़ा है क्योंकि आपको अपना छोटा ओएस बनाना होगा।

इंटेल मैनुअल

यद्यपि बिना किसी उदाहरण के समझना असंभव है, मैन्युअल रूप से जितनी जल्दी हो सके परिचित होने का प्रयास करें।

इंटेल इंटेल मैनुअल वॉल्यूम 3 सिस्टम प्रोग्रामिंग गाइड में पेजिंग का वर्णन करता है - 325384-056US सितंबर 2015 अध्याय 4 "पेजिंग"।

विशेष रूप से दिलचस्प है चित्रा 4-4 "32-बिट पेजिंग के साथ सीआर 3 और पेजिंग-संरचना प्रविष्टियों के प्रारूप", जो मुख्य डेटा संरचनाएं देता है।

MMU

पेजिंग सीपीयू के मेमोरी मैनेजमेंट यूनिट (एमएमयू) भाग द्वारा की जाती है। कई अन्य लोगों की तरह (जैसे x87 सह-प्रोसेसर , APIC ), यह शुरुआती दिनों में अलग चिप द्वारा उपयोग किया जाता था, जिसे बाद में सीपीयू में एकीकृत किया गया था। लेकिन शब्द अभी भी प्रयोग किया जाता है।

सामान्य तथ्य

तार्किक पते "नियमित" उपयोगकर्ता-भूमि कोड (जैसे mov eax, [rsi] में rsi की सामग्री) में उपयोग किए गए मेमोरी पते हैं।

पहला विभाजन उन्हें रैखिक पते में अनुवाद करता है, और उसके बाद पेजिंग फिर रैखिक पते को भौतिक पते में अनुवादित करता है।

(logical) ------------------> (linear) ------------> (physical)
             segmentation                 paging

अधिकांश समय, हम वास्तविक रैम हार्डवेयर मेमोरी कोशिकाओं को अनुक्रमणित करने के रूप में भौतिक पते के बारे में सोच सकते हैं, लेकिन यह 100% सच नहीं है क्योंकि:

पेजिंग केवल संरक्षित मोड में उपलब्ध है। संरक्षित मोड में पेजिंग का उपयोग वैकल्पिक है। पेजिंग पर है अगर cr0 रजिस्टर का PG बिट सेट है।

पेजिंग बनाम विभाजन

पेजिंग और सेगमेंटेशन के बीच एक बड़ा अंतर यह है कि:

  • पेजिंग रैम को बराबर आकार वाले हिस्सों में विभाजित करता है जिसे पेज कहा जाता है
  • विभाजन विभाजन मनमानी आकार के टुकड़ों में विभाजित करता है

यह पेजिंग का मुख्य लाभ है, क्योंकि बराबर आकार के टुकड़े चीजों को अधिक प्रबंधनीय बनाते हैं।

पेजिंग इतनी लोकप्रिय हो गई है कि विभाजन के लिए समर्थन 6486 बिट मोड में x86-64 में गिरा दिया गया था, नए सॉफ्टवेयर के लिए ऑपरेशन का मुख्य तरीका, जहां यह केवल संगतता मोड में मौजूद है, जो आईए 32 को अनुकरण करता है।

आवेदन

पेजिंग का उपयोग आधुनिक ओएस पर वर्चुअल एड्रेस रिक्त स्थान को कार्यान्वित करने के लिए किया जाता है। वर्चुअल पतों के साथ ओएस एक या एक से अधिक रैम पर दो या दो से अधिक समवर्ती प्रक्रियाओं को फिट कर सकता है:

  • दोनों कार्यक्रमों को दूसरे के बारे में कुछ भी जानने की जरूरत नहीं है
  • दोनों कार्यक्रमों की स्मृति आवश्यकतानुसार बढ़ सकती है और घट सकती है
  • कार्यक्रमों के बीच स्विच बहुत तेज है
  • एक प्रोग्राम कभी भी किसी अन्य प्रक्रिया की स्मृति तक नहीं पहुंच सकता है

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

हार्डवेयर कार्यान्वयन

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

उन डेटा संरचनाओं का प्रारूप हार्डवेयर द्वारा तय किया गया है , लेकिन यह उन डेटा संरचनाओं को सही तरीके से रैम पर सेट अप और प्रबंधित करने के लिए ओएस पर है, और हार्डवेयर को कहां से ढूंढना है ( cr3 माध्यम से)।

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

उदाहरण: सरलीकृत एकल-स्तरीय पेजिंग योजना

वर्चुअल मेमोरी स्पेस को लागू करने के लिए x86 आर्किटेक्चर के सरलीकृत संस्करण पर पेजिंग कैसे चलती है इसका यह एक उदाहरण है।

पेज टेबल

ओएस उन्हें निम्नलिखित पेज टेबल दे सकता है:

ओएस द्वारा प्रक्रिया 1 को दी गई पेज तालिका:

RAM location        physical address   present
-----------------   -----------------  --------
PT1 + 0       * L   0x00001            1
PT1 + 1       * L   0x00000            1
PT1 + 2       * L   0x00003            1
PT1 + 3       * L                      0
...                                    ...
PT1 + 0xFFFFF * L   0x00005            1

ओएस द्वारा प्रोसेस 2 को दी गई पेज टेबल:

RAM location       physical address   present
-----------------  -----------------  --------
PT2 + 0       * L  0x0000A            1
PT2 + 1       * L  0x0000B            1
PT2 + 2       * L                     0
PT2 + 3       * L  0x00003            1
...                ...                ...
PT2 + 0xFFFFF * L  0x00004            1

कहा पे:

  • PT1 और PT2 2: रैम पर तालिका 1 और 2 की प्रारंभिक स्थिति।

    नमूना मूल्य: 0x00000000 , 0x12345678 , आदि

    यह ओएस है जो उन मानों का फैसला करता है।

  • L : एक पेज टेबल प्रविष्टि की लंबाई।

  • present : इंगित करता है कि पृष्ठ स्मृति में मौजूद है।

पेज टेबल रैम पर स्थित हैं। उदाहरण के लिए वे इस प्रकार स्थित हो सकते हैं:

--------------> 0xFFFFFFFF


--------------> PT1 + 0xFFFFF * L
Page Table 1
--------------> PT1


--------------> PT2 + 0xFFFFF * L
Page Table 2
--------------> PT2

--------------> 0x0

दोनों पेज टेबल के लिए रैम पर शुरुआती स्थान मनमाने ढंग से और ओएस द्वारा नियंत्रित होते हैं। यह सुनिश्चित करने के लिए ओएस पर निर्भर है कि वे ओवरलैप नहीं करते हैं!

प्रत्येक प्रक्रिया सीधे किसी भी पेज टेबल को स्पर्श नहीं कर सकती है, हालांकि यह ओएस को अनुरोध कर सकती है जो पेज टेबल को संशोधित करने का कारण बनती है, उदाहरण के लिए बड़े ढेर या ढेर सेगमेंट के लिए पूछना।

एक पृष्ठ 4 केबी (12 बिट्स) का एक हिस्सा है, और चूंकि पते में 32 बिट्स हैं, प्रत्येक पृष्ठ की पहचान करने के लिए केवल 20 बिट्स (20 + 12 = 32, इस प्रकार हेक्साडेसिमल नोटेशन में 5 वर्ण) आवश्यक हैं। यह मान हार्डवेयर द्वारा तय किया गया है।

पेज टेबल प्रविष्टियां

एक पृष्ठ तालिका है ... पेज टेबल प्रविष्टियों की एक तालिका!

तालिका प्रविष्टियों का सटीक प्रारूप हार्डवेयर द्वारा तय किया जाता है

इस सरलीकृत उदाहरण पर, पृष्ठ तालिका प्रविष्टियों में केवल दो फ़ील्ड होते हैं:

bits   function
-----  -----------------------------------------
20     physical address of the start of the page
1      present flag

इसलिए इस उदाहरण में हार्डवेयर डिजाइनर L = 21

अधिकांश वास्तविक पृष्ठ तालिका प्रविष्टियों में अन्य फ़ील्ड होते हैं।

चीजों को 21 बाइट्स पर संरेखित करने के लिए अव्यवहारिक होगा क्योंकि स्मृति बाइट्स द्वारा संबोधित करने योग्य है और बिट्स नहीं है। इसलिए, इस मामले में केवल 21 बिट्स की आवश्यकता है, हार्डवेयर डिज़ाइनर संभवतया एक्सेस बनाने के लिए L = 32 का चयन करेंगे, और बाद में उपयोग के लिए शेष बिट्स को रिट करें। X86 पर L लिए वास्तविक मान 32 बिट्स है।

एकल स्तर की योजना में पता अनुवाद

एक बार ओएस द्वारा पेज टेबल स्थापित किए जाने के बाद, रैखिक और भौतिक पते के बीच पता अनुवाद हार्डवेयर द्वारा किया जाता है

जब ओएस प्रक्रिया 1 को सक्रिय करना चाहता है, तो यह प्रक्रिया 3 के लिए तालिका की शुरुआत, cr3 को PT1 1 पर सेट करता है।

यदि प्रक्रिया 1 रैखिक पता 0x00000001 तक पहुंचना चाहता है, तो पेजिंग हार्डवेयर सर्किट स्वचालित रूप से ओएस के लिए निम्न कार्य करता है:

  • रैखिक पते को दो भागों में विभाजित करें:

    | page (20 bits) | offset (12 bits) |
    

    तो इस मामले में हमारे पास होगा:

    • पृष्ठ = 0x00000
    • ऑफ़सेट = 0x001
  • पृष्ठ तालिका 1 में देखें क्योंकि cr3 अंक इसे इंगित करता है।

  • प्रविष्टि 0x00000 क्योंकि यह पृष्ठ भाग है।

    हार्डवेयर जानता है कि यह प्रविष्टि राम पते PT1 + 0 * L = PT1

  • चूंकि यह मौजूद है, एक्सेस मान्य है

  • पृष्ठ तालिका द्वारा, पृष्ठ संख्या 0x00000 का स्थान 0x00001 * 4K = 0x00001000

  • अंतिम भौतिक पता खोजने के लिए हमें ऑफसेट जोड़ने की आवश्यकता है:

      00001 000
    + 00000 001
      -----------
      00001 001
    

    क्योंकि 00001 पृष्ठ पर देखा गया पृष्ठ का भौतिक पता है और 001 ऑफ़सेट है।

    जैसा कि नाम इंगित करता है, ऑफसेट हमेशा पृष्ठ के भौतिक पते को जोड़ा जाता है।

  • तब हार्डवेयर उस भौतिक स्थान पर स्मृति प्राप्त करता है।

इसी तरह, प्रक्रिया 1 के लिए निम्नलिखित अनुवाद होंगे:

linear     physical
---------  ---------
00000 002  00001 002
00000 003  00001 003
00000 FFF  00001 FFF
00001 000  00000 000
00001 001  00000 001
00001 FFF  00000 FFF
00002 000  00002 000
FFFFF 000  00005 000

उदाहरण के लिए, पता 00001000 तक पहुंचने पर, पृष्ठ भाग 00001 है हार्डवेयर जानता है कि इसकी पृष्ठ तालिका प्रविष्टि रैम पते पर स्थित है: PT1 + 1 * L (पृष्ठ भाग के कारण 1 ), और यही वह जगह है जहां यह इसकी तलाश होगी ।

जब ओएस प्रक्रिया 2 पर स्विच करना चाहता है, तो इसे करने की ज़रूरत है कि पेज 3 पर cr3 बिंदु बनाना है। यह इतना आसान है!

अब प्रक्रिया के लिए निम्नलिखित अनुवाद होंगे 2:

linear     physical
---------  ---------
00000 002  00001 002
00000 003  00001 003
00000 FFF  00001 FFF
00001 000  00000 000
00001 001  00000 001
00001 FFF  00000 FFF
00003 000  00003 000
FFFFF 000  00004 000

एक ही रैखिक पता विभिन्न प्रक्रियाओं के लिए विभिन्न भौतिक पतों में अनुवाद करता है , केवल cr3 अंदर मूल्य के आधार पर।

इस तरह से प्रत्येक कार्यक्रम अपने डेटा को 0 से शुरू करने और सटीक भौतिक पते के बारे में चिंता किए बिना FFFFFFFF पर समाप्त होने की उम्मीद कर सकता है।

पृष्ठ गलती

क्या होगा यदि प्रक्रिया 1 किसी पृष्ठ के अंदर किसी पते का उपयोग करने का प्रयास करती है जो मौजूद नहीं है?

हार्डवेयर पेज फॉल्ट अपवाद के माध्यम से सॉफ़्टवेयर को सूचित करता है।

यह आमतौर पर यह तय करने के लिए अपवाद हैंडलर पंजीकृत करने के लिए ओएस तक होता है कि क्या किया जाना है।

यह संभव है कि किसी पृष्ठ को एक्सेस करना जो तालिका पर नहीं है प्रोग्रामिंग त्रुटि है:

int is[1];
is[2] = 1;

लेकिन ऐसे मामले हो सकते हैं जिनमें यह स्वीकार्य है, उदाहरण के लिए लिनक्स में:

  • कार्यक्रम अपने ढेर को बढ़ाना चाहता है।

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

  • पृष्ठ डिस्क पर बदल दिया गया था।

    पेज को वापस रैम में लाने के लिए ओएस को प्रक्रियाओं के पीछे कुछ काम करने की आवश्यकता होगी।

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

    उदाहरण के लिए लिनक्स पर, जब वर्तमान = 0:

    • यदि पृष्ठ तालिका प्रविष्टि के सभी फ़ील्ड 0, अमान्य पता हैं।

    • अन्यथा, पृष्ठ डिस्क पर बदल दिया गया है, और उन फ़ील्ड के वास्तविक मान डिस्क पर पृष्ठ की स्थिति को एन्कोड करते हैं।

किसी भी मामले में, ओएस को यह जानने की जरूरत है कि समस्या से निपटने में सक्षम होने के लिए कौन सा पता पृष्ठ दोष उत्पन्न हुआ है। यही कारण है कि जब भी पेज फॉल्ट होता है तो अच्छा IA32 डेवलपर्स उस पते पर cr2 का मान सेट करता है। अपवाद हैंडलर पता पाने के लिए बस cr2 देख सकते हैं।

सरलीकरण

वास्तविकता के लिए सरलीकरण जो इस उदाहरण को समझने में आसान बनाता है:

  • सभी वास्तविक पेजिंग सर्किट अंतरिक्ष बचाने के लिए बहु-स्तरीय पेजिंग का उपयोग करते हैं, लेकिन इससे एक सरल एकल-स्तरीय योजना दिखाई देती है।

  • पेज टेबल में केवल दो फ़ील्ड थे: एक 20 बिट एड्रेस और 1 बिट वर्तमान ध्वज।

    वास्तविक पृष्ठ सारणी में कुल 12 फ़ील्ड होते हैं, और इसलिए अन्य सुविधाएं जो छोड़ी गई हैं।

उदाहरण: बहु स्तरीय पेजिंग योजना

एक-स्तरीय पेजिंग योजना के साथ समस्या यह है कि यह बहुत अधिक रैम लेगा: प्रति प्रक्रिया 4 जी / 4 के = 1 एम प्रविष्टियां। यदि प्रत्येक प्रविष्टि 4 बाइट लंबी है, जो 4 एम प्रति प्रक्रिया करेगी, जो डेस्कटॉप कंप्यूटर के लिए भी बहुत अधिक है: ps -A | wc -l ps -A | wc -l कहना है कि मैं अभी 244 प्रक्रियाएं चला रहा हूं, इसलिए मेरी रैम लगभग 1 जीबी होगी!

इस कारण से, x86 डेवलपर्स ने एक बहु-स्तरीय योजना का उपयोग करने का निर्णय लिया जो रैम उपयोग को कम करता है।

इस प्रणाली का नकारात्मक हिस्सा यह है कि थोड़ा अधिक पहुंच का समय है।

पीएई के बिना 32 बिट प्रोसेसर के लिए उपयोग की जाने वाली सरल 3 स्तरीय पेजिंग योजना में, 32 पता बिट्स इस प्रकार विभाजित हैं:

| directory (10 bits) | table (10 bits) | offset (12 bits) |

प्रत्येक प्रक्रिया में एक और केवल एक पृष्ठ निर्देशिका से जुड़ा होना चाहिए, इसलिए इसमें कम से कम 2^10 = 1K पृष्ठ निर्देशिका प्रविष्टियां होंगी, जो एक-स्तरीय योजना पर आवश्यक न्यूनतम 1 एम से काफी बेहतर है।

पेज टेबल केवल ओएस द्वारा आवश्यक आवंटित किए जाते हैं। प्रत्येक पृष्ठ तालिका में 2^10 = 1K पृष्ठ निर्देशिका प्रविष्टियां होती हैं

पेज निर्देशिका में शामिल हैं ... पेज निर्देशिका प्रविष्टियां! पेज निर्देशिका प्रविष्टियां पृष्ठ तालिका प्रविष्टियों के समान होती हैं सिवाय इसके कि वे तालिकाओं के भौतिक पते की बजाय पृष्ठ सारणी के रैम पते को इंगित करते हैं । चूंकि वे पते केवल 20 बिट चौड़े हैं, इसलिए पेज टेबल 4KB पृष्ठों की शुरुआत में होना चाहिए।

cr3 अब पेज टेबल की बजाय वर्तमान प्रक्रिया की पेज निर्देशिका की रैम पर स्थान पर इंगित करता है।

पेज टेबल प्रविष्टियां एक-स्तरीय योजना से बिल्कुल नहीं बदलती हैं।

पेज टेबल एक-स्तरीय योजना से बदलते हैं क्योंकि:

  • प्रत्येक प्रक्रिया में 1K पृष्ठ सारणी हो सकती है, प्रति पृष्ठ निर्देशिका प्रविष्टि।
  • प्रत्येक पृष्ठ तालिका में 1 एम प्रविष्टियों के बजाय बिल्कुल 1K प्रविष्टियां होती हैं।

पहले दो स्तरों पर 10 बिट्स का उपयोग करने का कारण (और नहीं, कहें, 12 | 8 | 12 ) यह है कि प्रत्येक पृष्ठ तालिका प्रविष्टि 4 बाइट लंबी होती है। फिर पेज निर्देशिकाओं और पेज टेबल्स की 2 ^ 10 प्रविष्टियां अच्छी तरह से 4 केबी पृष्ठों में फिट होंगी। इसका मतलब है कि उस उद्देश्य के लिए पृष्ठों को आवंटित और हटाए जाने के लिए यह तेज़ और सरल है।

बहु-स्तरीय योजना में पता अनुवाद

ओएस द्वारा प्रक्रिया 1 को दी गई पृष्ठ निर्देशिका:

RAM location     physical address   present
---------------  -----------------  --------
PD1 + 0     * L  0x10000            1
PD1 + 1     * L                     0
PD1 + 2     * L  0x80000            1
PD1 + 3     * L                     0
...                                 ...
PD1 + 0x3FF * L                     0

PT1 = 0x10000000 ( 0x10000 * 4K) पर ओएस द्वारा 1 प्रक्रिया को संसाधित करने के लिए दी गई पृष्ठ सारणी:

RAM location      physical address   present
---------------   -----------------  --------
PT1 + 0     * L   0x00001            1
PT1 + 1     * L                      0
PT1 + 2     * L   0x0000D            1
...                                  ...
PT1 + 0x3FF * L   0x00005            1

PT2 = 0x80000000 ( 0x80000 * 4K) पर ओएस द्वारा 1 प्रक्रिया को संसाधित करने के लिए दी गई पृष्ठ सारणी:

RAM location      physical address   present
---------------   -----------------  --------
PT2 + 0     * L   0x0000A            1
PT2 + 1     * L   0x0000C            1
PT2 + 2     * L                      0
...                                  ...
PT2 + 0x3FF * L   0x00003            1

कहा पे:

  • PD1 : रैम पर प्रक्रिया 1 की पेज निर्देशिका की प्रारंभिक स्थिति।
  • PT1 और PT2 : रैम पर प्रक्रिया 1 के लिए पृष्ठ तालिका 1 और पृष्ठ तालिका 2 की प्रारंभिक स्थिति।

तो इस उदाहरण में पृष्ठ निर्देशिका और पृष्ठ तालिका रैम में संग्रहीत की जा सकती है जैसे कुछ:

----------------> 0xFFFFFFFF


----------------> PT2 + 0x3FF * L
Page Table 1
----------------> PT2

----------------> PD1 + 0x3FF * L
Page Directory 1
----------------> PD1


----------------> PT1 + 0x3FF * L
Page Table 2
----------------> PT1

----------------> 0x0

आइए चरणबद्ध रूप से रैखिक पता 0x00801004 चरण का अनुवाद करें।

हम मानते हैं कि cr3 = PD1 , यानी, यह वर्णित पृष्ठ निर्देशिका को इंगित करता है।

द्विआधारी में रैखिक पता है:

0    0    8    0    1    0    0    4
0000 0000 1000 0000 0001 0000 0000 0100

10 | 10 | 12 रूप में ग्रुपिंग 10 | 10 | 12 10 | 10 | 12 देता है:

0000000010 0000000001 000000000100
0x2        0x1        0x4

जो देता है:

  • पेज निर्देशिका प्रविष्टि = 0x2
  • पृष्ठ तालिका प्रविष्टि = 0x1
  • ऑफ़सेट = 0x4

तो हार्डवेयर पेज निर्देशिका के प्रवेश 2 के लिए देखता है।

पृष्ठ निर्देशिका तालिका का कहना है कि पृष्ठ तालिका 0x80000 * 4K = 0x80000000 पर स्थित है। यह प्रक्रिया की पहली रैम पहुंच है।

चूंकि पृष्ठ तालिका प्रविष्टि 0x1 , हार्डवेयर 0x80000000 पर पृष्ठ तालिका के प्रवेश 1 को देखता है, जो यह बताता है कि भौतिक पृष्ठ पता 0x0000C * 4K = 0x0000C000 पर स्थित है। यह प्रक्रिया की दूसरी रैम पहुंच है।

अंत में, पेजिंग हार्डवेयर ऑफ़सेट जोड़ता है, और अंतिम पता 0x0000C004

अनुवादित पते के अन्य उदाहरण हैं:

linear    10 10 12 split   physical
--------  ---------------  ----------
00000001  000 000 001      00001001
00001001  000 001 001      page fault
003FF001  000 3FF 001      00005001
00400000  001 000 000      page fault
00800001  002 000 001      0000A001
00801008  002 001 008      0000C008
00802008  002 002 008      page fault
00B00001  003 000 000      page fault

पृष्ठ त्रुटियां तब होती हैं जब कोई पृष्ठ निर्देशिका प्रविष्टि या पृष्ठ तालिका प्रविष्टि मौजूद न हो।

यदि ओएस एक साथ एक और प्रक्रिया को चलाने के लिए चाहता है, तो यह दूसरी प्रक्रिया को एक अलग पृष्ठ निर्देशिका प्रदान करेगा, और उस निर्देशिका को पृष्ठ सारणी को अलग करने के लिए लिंक करेगा।

64-बिट आर्किटेक्चर

वर्तमान बिट आकार के लिए 64 बिट्स अभी भी बहुत अधिक पता है, इसलिए अधिकांश आर्किटेक्चर कम बिट्स का उपयोग करेंगे।

x86_64 48 बिट्स (256 टीआईबी) का उपयोग करता है, और विरासत मोड का PAE पहले से ही 52-बिट पते (4 पीआईबी) की अनुमति देता है।

उन 48 बिट्स में से 12 ऑफसेट के लिए आरक्षित हैं, जो 36 बिट छोड़ देता है।

यदि 2 स्तर का दृष्टिकोण लिया जाता है, तो सबसे अच्छा विभाजन दो 18 बिट स्तर होगा।

लेकिन इसका मतलब यह होगा कि पेज निर्देशिका में 2^18 = 256K प्रविष्टियां होंगी, जो बहुत अधिक रैम लेती हैं: 32 बिट आर्किटेक्चर के लिए एकल-स्तरीय पेजिंग के करीब!

इसलिए, 64 बिट आर्किटेक्चर और भी पृष्ठ स्तर, आमतौर पर 3 या 4 बनाते हैं।

x86_64 9 | 9 | 9 | 12 में 4 स्तरों का उपयोग करता है 9 | 9 | 9 | 12 9 | 9 | 9 | 12 योजना, ताकि ऊपरी स्तर केवल 2^9 उच्च स्तरीय प्रविष्टियां लेता है।

पीएई

भौतिक पता विस्तार।

32 बिट्स के साथ, केवल 4 जीबी रैम को संबोधित किया जा सकता है।

यह बड़े सर्वरों के लिए एक सीमा बनना शुरू कर दिया, इसलिए इंटेल ने पेंटियम प्रो को पीएई तंत्र पेश किया।

समस्या से छुटकारा पाने के लिए, इंटेल ने 4 नई एड्रेस लाइनों को जोड़ा, ताकि 64 जीबी को संबोधित किया जा सके।

पीएई चालू होने पर पेज टेबल स्ट्रक्चर भी बदला जाता है। जिस सटीक तरीके से इसे बदला जाता है, मौसम पीएसई चालू या बंद होता है।

पीएई cr4 के PAE बिट के माध्यम से चालू और बंद है।

भले ही कुल एड्रेसेबल मेमोरी 64 जीबी है, फिर भी व्यक्तिगत प्रक्रिया अभी भी 4 जीबी तक का उपयोग करने में सक्षम है। हालांकि ओएस विभिन्न 4 जीबी हिस्सों पर विभिन्न प्रक्रियाएं डाल सकता है।

सार्वजनिक उपक्रम

पृष्ठ आकार विस्तार।

4K की बजाय लंबाई में पृष्ठों को 4 एम (या पीएई चालू होने पर 2 एम) होने की अनुमति देता है।

पीएसई cr4 के PAE बिट के माध्यम से चालू और बंद है।

पीएई और पीएसई पेज टेबल योजनाएं

यदि पीएई और पीएसई सक्रिय हैं, तो विभिन्न पेजिंग स्तरीय योजनाओं का उपयोग किया जाता है:

  • कोई पीएई नहीं और कोई पीएसई नहीं: 10 | 10 | 12 10 | 10 | 12

  • कोई पीएई और पीएसई: 10 | 22 10 | 22

    22 4 एमबी पेज के भीतर ऑफसेट है, क्योंकि 22 बिट्स 4 एमबी पते हैं।

  • पीएई और कोई पीएसई: 2 | 9 | 9 | 12 2 | 9 | 9 | 12

    डिज़ाइन का कारण 9 क्यों 10 के बजाए दो बार उपयोग किया जाता है यह है कि अब प्रविष्टियां 32 बिट्स में फिट नहीं हो सकती हैं, जो सभी 20 पता बिट्स और 12 सार्थक या आरक्षित ध्वज बिट्स से भरे हुए थे।

    कारण यह है कि पेज बिट्स के पते का प्रतिनिधित्व करने के लिए अब 20 बिट पर्याप्त नहीं हैं: प्रोसेसर में जोड़े गए 4 अतिरिक्त तारों के कारण अब 24 बिट्स की आवश्यकता है।

    इसलिए, डिजाइनरों ने 64 बिट्स में प्रवेश आकार बढ़ाने का फैसला किया, और उन्हें एक पृष्ठ तालिका में फिट करने के लिए आवश्यक है, इसलिए आवश्यक है कि प्रविष्टियों की संख्या 2 ^ 10 के बजाय 2 ^ 9 तक कम हो।

    शुरुआती 2 पृष्ठ निर्देशिका सूचक तालिका (पीडीपीटी) नामक एक नया पृष्ठ स्तर है, क्योंकि यह पृष्ठ निर्देशिकाओं को इंगित करता है और 32 बिट रैखिक पते को भरता है। पीडीपीटी 64 बिट चौड़े भी हैं।

    cr3 अब cr3 को इंगित करता है जो मुट्ठी पर चार 4 जीबी मेमोरी पर होना चाहिए और दक्षता को संबोधित करने के लिए 32 बिट गुणकों पर गठबंधन होना चाहिए। इसका मतलब यह है कि अब cr3 3 में 32 गुणक * 2 ^ 27 के लिए 20: 2 ^ 5 की बजाय 27 महत्त्वपूर्ण बिट्स हैं, जो पहले 4 जीबी के 2 ^ 32 को पूरा करने के लिए हैं।

  • पीएई और पीएसई: 2 | 9 | 21 2 | 9 | 21

    डिजाइनरों ने इसे एक पृष्ठ में फिट करने के लिए 9 बिट चौड़ा क्षेत्र रखने का फैसला किया।

    यह 23 बिट छोड़ देता है। पीडीईटी के लिए पीएई मामले के साथ चीजों को समान रखने के लिए पीडीपीटी के लिए 2 छोड़ना ऑफसेट के लिए 21 छोड़ देता है, जिसका अर्थ है कि पृष्ठ 4 एम के बजाय 2 एम चौड़े हैं।

TLB

अनुवाद लुकहेड बफर (टीएलबी) पेजिंग पते के लिए एक कैश है।

चूंकि यह एक कैश है, यह सीपीयू कैश के कई डिज़ाइन मुद्दों को साझा करता है, जैसे कि सहयोगी स्तर।

यह अनुभाग 4 एकल पता प्रविष्टियों के साथ सरलीकृत पूरी तरह से सहयोगी टीएलबी का वर्णन करेगा। ध्यान दें कि अन्य कैश की तरह, वास्तविक टीएलबी आमतौर पर पूरी तरह से सहयोगी नहीं होते हैं।

मूल परिचालन

रैखिक और भौतिक पता के बीच अनुवाद के बाद, यह टीएलबी पर संग्रहीत होता है। उदाहरण के लिए, निम्नलिखित स्थिति में एक 4 प्रविष्टि टीएलबी शुरू होता है:

  valid   linear   physical
  ------  -------  ---------
> 0       00000    00000
  0       00000    00000
  0       00000    00000
  0       00000    00000

> वर्तमान प्रविष्टि को प्रतिस्थापित करने का संकेत देता है।

और एक पृष्ठ रैखिक पता 00003 बाद एक भौतिक पता 00005 अनुवाद किया जाता है, 00005 बन जाता है:

  valid   linear   physical
  ------  -------  ---------
  1       00003    00005
> 0       00000    00000
  0       00000    00000
  0       00000    00000

और 00007 से 00009 दूसरे अनुवाद के बाद यह बन जाता है:

  valid   linear   physical
  ------  -------  ---------
  1       00003    00005
  1       00007    00009
> 0       00000    00000
  0       00000    00000

अब अगर 00003 को दोबारा अनुवादित करने की ज़रूरत है, तो हार्डवेयर पहले 00003 --> 00005 देखता है और एक ही रैम एक्सेस 00003 --> 00005 साथ अपना पता पाता है।

बेशक, 00000 पर नहीं है क्योंकि किसी वैध प्रविष्टि में एक कुंजी के रूप में 00000 शामिल नहीं है।

प्रतिस्थापन नीति

जब टीएलबी भर जाता है, तो पुराने पते ओवरराइट किए जाते हैं। सीपीयू कैश की तरह ही, प्रतिस्थापन नीति एक संभावित जटिल ऑपरेशन है, लेकिन कम से कम हाल ही में उपयोग की जाने वाली प्रविष्टि (एलआरयू) को हटाने के लिए एक सरल और उचित ह्युरिस्टिक है।

एलआरयू के साथ, राज्य से शुरू:

  valid   linear   physical
  ------  -------  ---------
> 1       00003    00005
  1       00007    00009
  1       00009    00001
  1       0000B    00003

0000D -> 0000A जोड़ना 0000D -> 0000A दे देंगे:

  valid   linear   physical
  ------  -------  ---------
  1       0000D    0000A
> 1       00007    00009
  1       00009    00001
  1       0000B    00003

सीएएम

टीएलबी का उपयोग करना अनुवाद को तेज़ी से बनाता है, क्योंकि प्रारंभिक अनुवाद प्रति टीएलबी स्तर पर एक पहुंच लेता है , जिसका मतलब है कि साधारण 32 बिट योजना पर 2, लेकिन 64 बिट आर्किटेक्चर पर 3 या 4।

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

रैम पते पर मैपिंग भी लागू की जा सकती है, लेकिन सीएएम मैपिंग को रैम मैपिंग की तुलना में बहुत कम प्रविष्टियों की आवश्यकता हो सकती है।

उदाहरण के लिए, एक नक्शा जिसमें:

  • दोनों चाबियों और मानों में 20 बिट्स हैं (एक साधारण पेजिंग योजनाओं का मामला)
  • प्रत्येक 4 मूल्यों पर हर समय स्टोर करने की आवश्यकता होती है

4 प्रविष्टियों के साथ एक टीएलबी में संग्रहीत किया जा सकता है:

linear   physical
-------  ---------
00000    00001
00001    00010
00010    00011
FFFFF    00000

हालांकि, इसे रैम के साथ लागू करने के लिए, 2 ^ 20 पते होना आवश्यक होगा :

linear   physical
-------  ---------
00000    00001
00001    00010
00010    00011
... (from 00011 to FFFFE)
FFFFF    00000

जो एक टीएलबी का उपयोग करने से भी अधिक महंगा होगा।

अमान्य प्रविष्टियां

जब cr3 बदलता है, तो सभी cr3 प्रविष्टियों को अमान्य कर दिया जाता है, क्योंकि एक नई प्रक्रिया के लिए एक नई पेज तालिका का उपयोग किया जा रहा है, इसलिए यह संभावना नहीं है कि पुरानी प्रविष्टियों में से कोई भी अर्थ हो।

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

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

लिनक्स कर्नेल उपयोग

लिनक्स कर्नेल छोटे डेटा विखंडन के साथ तेज प्रक्रिया स्विच की अनुमति देने के लिए x86 की पेजिंग विशेषताओं का व्यापक उपयोग करता है।

v4.2 , arch/x86/ अंतर्गत देखें:

  • include/asm/pgtable*
  • include/asm/page*
  • mm/pgtable*
  • mm/page*

पृष्ठों का प्रतिनिधित्व करने के लिए परिभाषित कोई भी structs नहीं लगता है, केवल मैक्रोज़: include/asm/page_types.h विशेष रूप से दिलचस्प है। अंश:

#define _PAGE_BIT_PRESENT   0   /* is present */
#define _PAGE_BIT_RW        1   /* writeable */
#define _PAGE_BIT_USER      2   /* userspace addressable */
#define _PAGE_BIT_PWT       3   /* page write through */

arch/x86/include/uapi/asm/processor-flags.h CR0 को परिभाषित करता है, और विशेष रूप से PG बिट स्थिति:

#define X86_CR0_PG_BIT      31 /* Paging */

ग्रन्थसूची

मुक्त:

  • rutgers-pxk-416 अध्याय "मेमोरी प्रबंधन: व्याख्यान नोट्स"

    पुराने ओएस द्वारा उपयोग की जाने वाली स्मृति संगठन तकनीकों की अच्छी ऐतिहासिक समीक्षा।

गैर-मुक्त:

  • bovet05 अध्याय "मेमोरी एड्रेसिंग"

    X86 मेमोरी एड्रेसिंग के लिए उचित परिचय। कुछ अच्छे और सरल उदाहरण गुम हैं।