Windows मेमोरी की गहराई (भाग 1) — वह क्षण जब आभासी पता भौतिक RAM बन जाता है: शुरू से अंत तक page fault

· · Windows, मेमोरी प्रबंधन, VirtualAlloc, Page fault, VAD, प्रदर्शन निगरानी

VirtualAlloc को MEM_COMMIT देने से उसी क्षण Commit बढ़ता है। Working Set, फिर भी, उतनी ही मात्रा नहीं बढ़ता। तो वह मेमोरी कहाँ है जिसे आपने आवंटित सोचा था?

उत्तर यह है कि अधिकतर पेजों के पास अभी संगत भौतिक RAM नहीं है। Windows भौतिक पेज सौंपना तब तक टालता है जब तक अनुप्रयोग वास्तव में पेज को छुए। जब पहली पहुँच CPU से page fault उठवाती है, मेमोरी प्रबंधक VAD, PTE, सुरक्षा गुण और backing store जाँचता है, और ज़रूरत हो तो RAM को एक-एक पेज बाँधता है।1

यह लेख उस रास्ते का अनुसरण करता है जो «पहला बाइट जिसे आप छूते हैं» भौतिक RAM तक चलता है। यदि पहले Working Set और Commit जैसी संख्याओं का अर्थ सुलझाना हो, परिचयात्मक लेख «What Does Windows’ “Memory Usage” Actually Mean? — Correctly Reading Working Set, Private Bytes, Commit, and the Page File» देखें। यह श्रृंखला वहाँ प्रयुक्त शब्दों को फिर परिभाषित नहीं करती; यह तंत्र की ओर से खोदती है कि «संख्या वैसी क्यों निकलती है»।

«Windows मेमोरी की गहराई» — सभी 3 भाग

  1. भाग 1 (यह लेख): आभासी पते और page fault
    हम देखते हैं कि VirtualAlloc से आवंटित क्षेत्र कब भौतिक RAM पाता है।
  2. भाग 2: एक भौतिक पेज का जीवन
    हम देखते हैं कि Working Set से निकला पेज Modified, Standby, Free और Zeroed से कैसे चलता है।
  3. भाग 3: सेक्शन ऑब्जेक्ट और copy-on-write
    हम देखते हैं कि DLL, फ़ाइल मैपिंग और साझा मेमोरी भौतिक पेज क्यों साझा कर सकती हैं।

भाग 1 जो प्रश्न हल करता है वह केवल एक है।

Commit हो चुका आभासी पता किस क्षण भौतिक RAM बनता है?

लक्षित पाठक वे डेवलपर और संचालक हैं जो तंत्र से Windows ऐप मेमोरी उपयोग, स्टार्टअप के तुरंत बाद page fault, 0xC0000005, तथा VMMap और PerfMon की संख्याएँ समझना चाहते हैं। पूर्वपेक्षाएँ Windows 10/11 या वर्तमान Windows Server हैं, और आवश्यक पृष्ठभूमि पॉइंटर तथा VirtualAlloc की मूल बातें हैं; पेज-टेबल बिट लेआउट या कर्नेल डिबगर का अनुभव नहीं चाहिए। कठिनाई मध्यम है। हम आंतरिक संरचनाओं के नाम इस्तेमाल करते हैं, पर किसी खास Windows बिल्ड पर निर्भर अदस्तावेजित लेआउट नहीं मानते।

1. पहले निष्कर्ष

सामान्य निजी-मेमोरी प्रवाह, एक पंक्ति में, यह है।

Reserve आभासी पता सीमा अलग रखता है, Commit भविष्य में सामग्री रखने की जगह गारंटी देने के लिए सिस्टम की commit सीमा के विरुद्ध commit चार्ज करता है, और पहली पहुँच का page fault भौतिक पेज सौंपता है।

अर्थात् MEM_COMMIT वह आदेश नहीं जो कहे «अभी RAM आवंटित करो»। Microsoft का VirtualAlloc दस्तावेज़ भी गारंटी देता है कि Commit पेज की प्रारंभिक सामग्री शून्य है, और समझाता है कि वास्तविक भौतिक पेज आभासी पते तक पहुँच तक नहीं सौंपा जाता।1

इतना कहकर, यह दावा भी गलत है कि «Reserve/Commit केवल VAD में लिखते हैं»। व्यवहार में Reserve मुख्यतः वह VAD बनाता है जो आभासी पता सीमा और उसके गुण दर्शाता है, और Commit सिस्टम का Commit Total बढ़ाता है तथा सीमा की commit स्थिति दर्ज करता है। मध्य पेज-टेबल स्तर और अलग PTE ज़रूरत पर आलसी बनते हैं, और भौतिक RAM से अंतिम बंधन आमतौर पर पहली पहुँच पर होता है।

Commit खाली वादा नहीं; यह पूरे सिस्टम का वादा है कि सामग्री भविष्य में RAM या उपयुक्त backing store में रखी जा सकेगी। वह प्रवेश बिंदु जो इस वादे को एक-एक पेज साकार करता है, page fault है।

Reserve, Commit और पहली पहुँच पर क्या होता हैMEM_RESERVE सीमा और गुण VAD में दर्ज करता है, MEM_COMMIT भंडारण का वादा करने के लिए Commit Total खर्च करता है, और पहली पहुँच का page fault भौतिक पेज सौंपकर Working Set में जोड़ता है1. MEM_RESERVE2. MEM_COMMIT3. पहली पहुँच(Touch)सीमा और गुण VAD में दर्ज करेंCommit Total खर्च करें(अभी भौतिक पेज नहीं)Page faultशून्य किया भौतिक पेज PTE से बाँधेंWorking Set में जोड़ें और निर्देश फिर चलाएँ

चित्र 1: Reserve, Commit और Touch अलग घटनाएँ हैं। भौतिक RAM केवल अंतिम चरण, पहली पहुँच, पर बाँधी जाती है।

2. तीन खाते जो आभासी पेज का पीछा करते हैं

आभासी पते से भौतिक RAM तक का रास्ता समझने के लिए Windows के तीन खातों को अलग करना चाहिए।

खाता इकाई भूमिका
VAD आभासी पता सीमा क्षेत्र क्या है, Reserve/Commit, सुरक्षा और सेक्शन संगति संभालता है
पेज टेबल / PTE आभासी पेज भौतिक पेज तक वर्तमान अनुवाद, या अनसाकार स्थिति दर्शाता है
PFN डेटाबेस भौतिक पेज प्रत्येक RAM पेज का स्वामित्व, संदर्भ और स्थिति ट्रैक करता है

VAD सीमा की जानकारी रखता है, PTE आभासी पेज की, और PFN डेटाबेस भौतिक पेज की। page-fault हैंडलर इन्हें मिलाकर तय करता है कि पहुँच जारी रह सकती है या नहीं।

आभासी पते से भौतिक RAM तक तीन खातेआभासी पते को VAD सीमा कणिकता पर और PTE आभासी-पेज कणिकता पर संभालता है, और PFN डेटाबेस PTE के अनुवाद लक्ष्य भौतिक पेज को भौतिक-पेज कणिकता पर ट्रैक करता हैReserve/Commit और सुरक्षा आँकेंमान्य अनुवादआभासी पताVAD(सीमा खाता)PTE(आभासी-पेज खाता)PFN डेटाबेस(भौतिक-पेज खाता)भौतिक RAM पेज

चित्र 2: अलग कणिकता के तीन खाते। Fault प्रबंधन VAD और PTE मिलाता है, फिर परिणाम PFN पक्ष पर दर्शाता है।

इस लेख के नायक VAD और PTE हैं। PFN डेटाबेस को हम भाग 2 में भौतिक-पेज पक्ष से देखेंगे।

3. Reserve, Commit और Touch अलग घटनाएँ हैं

3.1. Reserve — एक पता दावा करना

पहले, 256MiB की सतत आभासी पता सीमा आरक्षित करें।

void* base = VirtualAlloc(
    nullptr,
    256ull * 1024 * 1024,
    MEM_RESERVE,
    PAGE_NOACCESS);

इस बिंदु पर केवल यही हुआ कि प्रक्रिया के आभासी स्थान में एक पता अलग रखा गया ताकि अन्य आवंटन इस सीमा का उपयोग न कर सकें। MEM_RESERVE RAM या पेज फ़ाइल में कोई भौतिक भंडारण नहीं सौंपता।1

क्योंकि 64-बिट प्रक्रिया का आभासी स्थान बहुत बड़ा है, पहले बड़ी सीमा Reserve करना और बाद में केवल ज़रूरी भाग Commit करना व्यावहारिक हो जाता है।

3.2. Commit — वादा कि रखा जा सकेगा

फिर आरक्षित सीमा को Commit करें।

void* committed = VirtualAlloc(
    base,
    256ull * 1024 * 1024,
    MEM_COMMIT,
    PAGE_READWRITE);

सफलता पर वह वादा की गई मात्रा बढ़ती है जो सिस्टम के Commit Total — और आमतौर पर प्रक्रिया के Private Bytes — में झलकती है। फिर भी 256MiB भौतिक पेज एक साथ नहीं खड़े होते। सामान्य पेज पहली पहुँच तक भौतिक रूप से अनसौंपे रहते हैं।12

तो Commit का मतलब क्या है? यह कि जब सिस्टम वादा नहीं ले सकता, वह Commit के समय विफलता लौटा सकता है, मेमोरी इस्तेमाल के बीच में नहीं।

3.3. Touch — जब भौतिक पेज आवश्यक हो जाता है

अंत में, निम्नलिखित असाइनमेंट पहली बार पहले पेज पर लिखता है।

static_cast<unsigned char*>(base)[0] = 1;

CPU आभासी पते को भौतिक पते में अनुवाद करने की कोशिश करता है, पर PTE के पास अभी भौतिक पेज का मान्य अनुवाद नहीं है। यहाँ page fault होता है।

नियंत्रण पाने वाला मेमोरी प्रबंधक इसे «Commit और लिखने योग्य निजी पेज पर पहली पहुँच» मानता है, शून्य किया भौतिक पेज लेता है, PTE से बाँधता है, और Working Set में जोड़ता है। फिर वह असफल लेखन निर्देश फिर चलाता है।

ऐप से यह साधारण असाइनमेंट लगता है, पर भीतर असाइनमेंट के बीच नियंत्रण कर्नेल में जाता है, भौतिक पेज सौंपा जाता है, और निष्पादन उसी निर्देश पर लौटता है

4. VAD — आभासी स्थान का सीमा खाता

VAD का मतलब Virtual Address Descriptor है, और Windows प्रक्रिया की उपयोग में पता सीमाओं को VAD के वृक्ष के रूप में संभालता है। WinDbg के !vad से आप आरंभ और अंत VPN, Commit, सुरक्षा गुण, Private/Mapped, Control Area और और भी देख सकते हैं।3

VAD जो प्रतिनिधि जानकारी दर्ज करता है उसमें ये शामिल हैं।

  • पता सीमा का आरंभ और अंत
  • प्रकार, जैसे Private, Mapped या Image
  • Reserve/Commit स्थिति
  • पढ़ना, लिखना, चलाना और copy-on-write जैसी सुरक्षा
  • फ़ाइल या सेक्शन से संगति
  • गार्ड पेज जैसे विशेष गुण

सीमा से संभालने का कारण दक्षता है। 256MiB 4KiB पर 65,536 पेज हैं। हर पेज के लिए पहले से पूर्ण प्रबंधन संरचना बनाने के बजाय, VAD में «यह सतत सीमा एक आरक्षण है» रखना और ज़रूरत पड़ने पर पेज साकार करना कम अपव्यय है।

4.1. VAD मिलना पुनर्प्राप्ति की गारंटी नहीं

«यदि VAD में है तो fault सुलझता है; नहीं तो पहुँच उल्लंघन» सुविधाजनक प्रारंभिक व्याख्या है, पर अतिसरल है। VAD मिलने पर भी सामान्य पहुँच इन जैसे मामलों में जारी नहीं रह सकती।

  • केवल Reserve, और लक्ष्य पेज Commit नहीं
  • PAGE_NOACCESS
  • केवल-पढ़ने पेज पर लेखन
  • गैर-चलने योग्य पेज से निर्देश चलाना
  • गार्ड पेज का पहला स्पर्श
  • सेक्शन की मान्य सीमा से बाहर स्पर्श

उलटा, भले PTE अमान्य हो, यदि VAD और PTE की सॉफ़्टवेयर स्थिति वैध पहुँच दिखाए, तो demand-zero, Transition पुनर्स्थापना, page-in या CoW से सुलझाया जा सकता है। अधिक सटीक उत्तर है VAD, PTE, सुरक्षा गुण और पहुँच प्रकार साथ आँकें

5. पेज टेबल और TLB

ऐप जो पॉइंटर रखता है वह आभासी पता है। CPU के RAM तक पहुँचने के लिए आभासी पेज संख्या को भौतिक पेज संख्या में अनुवाद करना होगा। वह पदानुक्रमित अनुवाद तालिका पेज टेबल है, और पत्ती प्रविष्टि PTE (Page Table Entry) है।

मान्य PTE अवधारणात्मक रूप से PFN, पढ़ना/लिखना/चलाना सुरक्षा, उपयोगकर्ता-मोड अनुमति, Accessed/Dirty और ऐसी जानकारी रखती है। वास्तविक बिट लेआउट CPU और Windows संस्करण पर निर्भर है।

हर बार पेज टेबल चलना बहुत धीमा होगा, इसलिए CPU हाल के अनुवाद TLB (Translation Lookaside Buffer) में कैश करता है। पता अनुवाद इस क्रम में चलता है।

  1. यदि TLB में अनुवाद है और पहुँच उस सुरक्षा से मेल खाती है, वह परिणाम प्रयुक्त होता है।
  2. यदि TLB में अनुवाद नहीं, CPU पेज टेबल चलता है।
  3. यदि मान्य PTE है और सुरक्षा भी मेल खाती है, वह TLB में दर्ज होती है और निष्पादन जारी रहता है।
  4. यदि मान्य अनुवाद नहीं, या सुरक्षा उल्लंघन है, नियंत्रण page-fault प्रवेश बिंदु पर जाता है। सुरक्षा जाँच तब भी होती है जब अनुवाद TLB से आया हो।

जैसा यह प्रवाह दिखाता है, TLB miss और page fault अलग चीज़ें हैं। यदि एकमात्र समस्या यह है कि TLB में अनुवाद नहीं और PTE मान्य है, केवल पेज-टेबल वॉक होता है। उलटा, भले TLB में अनुवाद हो, केवल-पढ़ने पेज पर लेखन या गैर-चलने योग्य पेज पर निर्देश चलाना जैसा सुरक्षा उल्लंघन page-fault प्रवेश बिंदु पर जाता है। इसलिए CoW पेज पर लेखन fault कर सकता है भले अनुवाद पहले से कैश हो।

पता-अनुवाद प्रवाह और page-fault प्रवेश बिंदुभले TLB में अनुवाद हो, सुरक्षा बेमेल page-fault प्रवेश बिंदु पर जाता है। यदि TLB में अनुवाद नहीं तो पेज टेबल चली जाती है; मान्य PTE जो सुरक्षा से भी मेल खाए TLB में दर्ज होती है और निष्पादन जारी रहता है, और अमान्य अनुवाद या सुरक्षा उल्लंघन page-fault प्रवेश बिंदु पर जाता हैहाँमेलसुरक्षा उल्लंघननहींहाँअमान्य या सुरक्षा उल्लंघनमेमोरी पहुँचक्या TLB में अनुवाद है?क्या पहुँच सुरक्षा से मेल खाती है?उस अनुवाद से जारी रखेंpage-fault प्रवेश बिंदु परपेज-टेबल वॉकमान्य PTE और सुरक्षा भी मेल?TLB में दर्ज करें और जारी रखें(कोई fault नहीं)

चित्र 3: TLB miss पेज-टेबल वॉक से सुलझ सकता है। नियंत्रण page fault पर जाता है जब अनुवाद अमान्य हो या सुरक्षा उल्लंघन हो, और सुरक्षा उल्लंघन TLB hit पर भी होता है।

5.1. अमान्य PTE केवल खाली नहीं

अमान्य PTE भी खाली नहीं। अमान्य PTE की सॉफ़्टवेयर स्थिति से Windows ये जैसे मामले अलग करता है।

  • demand-zero पेज जो कभी साकार नहीं हुआ
  • Transition पेज जो RAM में रहता है
  • साझा पेज जो Prototype PTE का संदर्भ देता है
  • पेज फ़ाइल में सहेजा निजी पेज
  • सुरक्षा उल्लंघन या अमान्य क्षेत्र

CPU का काम केवल यह तय करना है «यह सामान्य मान्य अनुवाद नहीं» और कर्नेल को सौंपना; अर्थ वहाँ से मेमोरी प्रबंधक देता है।

6. शुरू से अंत तक एक page fault

Commit निजी पेज पर पहली लेखन को छह चरणों में देखें।

  1. CPU लिखने की कोशिश करता है।
    वह TLB और पेज टेबल जाँचता है, पर लक्ष्य PTE के पास मान्य PFN नहीं।
  2. CPU page fault उठाता है।
    वह fault वाले आभासी पते, पढ़ना/लिखना/चलाना प्रकार, उपयोगकर्ता/कर्नेल, और समस्या अनुवाद की कमी है या सुरक्षा उल्लंघन, कर्नेल को देता है।
  3. मेमोरी प्रबंधक VAD और PTE जाँचता है।
    वह तय करता है कि पेज Commit है या नहीं, सुरक्षा मेल खाती है या नहीं, और demand-zero, Transition, साझा, page-in, CoW या अपवाद में से कौन लागू है।
  4. यदि demand-zero है, शून्य किया भौतिक पेज लिया जाता है।
    नया सौंपा पेज शून्य होना चाहिए ताकि दूसरी प्रक्रिया का डेटा न लीक हो।
  5. PTE और PFN प्रबंधन जानकारी अपडेट होती है।
    PTE में PFN और सुरक्षा सेट होते हैं, भौतिक पेज Active बनता है, और प्रक्रिया के Working Set में जुड़ता है।
  6. असफल निर्देश फिर चलता है।
    क्योंकि fault सामान्य सुलझा, कोई उपयोगकर्ता-मोड अपवाद नहीं दिया जाता, और ऐप असाइनमेंट सामान्य जारी रखता है।

ETW page-fault घटनाएँ Transition, Demand Zero, Copy-on-Write, Guard Page, Hard Page Fault और Access Violation को अलग प्रकारों के रूप में भी दर्ज करती हैं।4

इसलिए page fault शुरू से «असामान्य» का शब्द नहीं। यह साझा प्रवेश बिंदु है जब CPU सामान्य पथ पर अनुवाद नहीं कर सका तो OS से निर्णय माँगने का।

page-fault समाधानों की शाखामेमोरी प्रबंधक VAD, PTE, सुरक्षा गुण और पहुँच प्रकार आँकता है, और demand-zero, RAM में बचे पेज को फिर जोड़ना, backing store से hard fault, copy-on-write, गार्ड-पेज सूचना या अपवाद पर भेजता हैपहली पहुँचअभी RAM मेंडिस्क पढ़ना चाहिएCoW लेखनगार्ड पेजअसुलझाPage fault होता हैVAD, PTE, सुरक्षा, प्रकार आँकेंDemand-zero(नरम)Standby से फिर जोड़ें(नरम)Hard fault(डिस्क I/O)कॉपी करें और PTE बदलेंगार्ड हटाएँ और सूचित करेंअपवाद(0xC0000005 आदि)

चित्र 4: एक ही प्रवेश बिंदु से आए fault आँकने के अनुसार छह परिणामों में बँटते हैं। गार्ड पेज विवरण खंड 9 में हैं।

7. Demand-zero — soft fault जो डिस्क नहीं पढ़ता

Demand-zero वह प्रतिनिधि soft fault है जो Commit निजी पेज पहली बार छूने पर होता है। Microsoft का Working Set दस्तावेज़ «प्रक्रिया आवंटित आभासी पेज का पहली बार संदर्भ देती है» को भी soft fault का उदाहरण मानता है।5

Demand-zero की ये विशेषताएँ हैं।

  • डिस्क से मूल डेटा पढ़ने की ज़रूरत नहीं
  • प्रारंभिक सामग्री शून्य है
  • उपलब्ध भौतिक पेज बाँधा जाता है
  • Working Set और संचयी Page Fault Count बढ़ते हैं
  • अकेले यह प्रबंधन Memory\\Pages Input/sec नहीं बढ़ाता

इसीलिए स्टार्टअप के तुरंत बाद Page Faults/sec का उछाल अपने आप यह नहीं कहता कि स्टोरेज अड़चन है।

आलसी आवंटन का समझौता भी सुलझाना चाहिए। यदि आप 256MiB Commit करें और वास्तव में केवल 8MiB इस्तेमाल करें, शेष 248MiB को RAM से बाहर छोड़ना उचित है। बदले में पहली पहुँच fault प्रबंधन की लागत उठाती है। विलंब-संवेदनशील काम के लिए एक डिज़ाइन है जो शुरू से पहले हर पेज छूकर prefault करता है, पर वह समझौता है जो पहले से RAM निवास बढ़ाता है।

8. Soft fault और hard fault

8.1. Soft fault

Soft fault वह fault है जो backing store पर पढ़ने I/O के बिना सुलझ सकता है। प्रतिनिधि उदाहरणों में ये शामिल हैं।

  • Demand-zero
  • Standby/Transition पर बचे पेज को फिर जोड़ना
  • दूसरे प्रक्रिया के Working Set में साझा पेज जोड़ना
  • पहले से लाए पेज को जोड़ना
  • Copy-on-Write जिसका मूल पेज निवासी है

कर्नेल संक्रमण, लॉक, PTE/PFN अपडेट, TLB संगति आदि की CPU लागत अभी भी है, पर स्टोरेज प्रतीक्षा नहीं।5

8.2. Hard fault

दूसरी ओर, जब ज़रूरी पेज RAM में कहीं नहीं और backing store से पढ़ना हो, वह hard fault है। पढ़ने का स्रोत केवल पेज फ़ाइल नहीं।

  • पेज फ़ाइल में लिखा निजी पेज
  • मेमोरी-मैप की गई फ़ाइल
  • EXE या DLL छवि
  • फ़ाइल कैश द्वारा संदर्भित डेटा फ़ाइल

ETW HardFault घटनाओं में FileObject, ReadOffset और ByteCount हैं, इसलिए वास्तविक पढ़ने स्रोत ट्रैक किया जा सकता है।6

इसलिए Hard Fault = pagefile.sys का पढ़ना सत्य नहीं।

जब backing-store पढ़ना चाहिए, अनुरोध Windows I/O स्टैक में जाता है। IRP और जारी/पूर्णता का प्रवाह «The Depths of Windows I/O (Part 1)» में है, और फ़ाइल कैश से जोड़ «The Depths of Windows I/O (Part 4)» में है। यदि पेज RAM में है मेमोरी प्रबंधक स्वयं लौट सकता है; यदि नहीं, वह I/O जारी करता है और पूर्णता तक fault थ्रेड की प्रतीक्षा करता है।

9. असुलझा fault अपवाद बनता है

वह fault जो VAD और PTE जाँचने के बाद वैध आवंटन, page-in या CoW के रूप में सुलझ न सके, उपयोगकर्ता मोड को अपवाद के रूप में दिया जाता है।

प्रतिनिधि मामला STATUS_ACCESS_VIOLATION है, अपवाद कोड 0xC0000005। यह अमान्य पते के पढ़ने, लिखने या चलाने पर होता है; पहला अपवाद पैरामीटर पहुँच प्रकार बताता है और दूसरा उल्लंघन पता।7

विशिष्ट पैटर्न में ये शामिल हैं।

  • NULL, मुक्त किया पता या सरणी से बाहर पता पढ़ना
  • केवल-पढ़ने पेज पर लिखना
  • उस पेज से निर्देश चलाना जिसे DEP/NX ने गैर-चलने योग्य बनाया
  • आरक्षित पर Commit न की सीमा छूना

PAGE_GUARD का अर्थ थोड़ा अलग है। यह पहुँच की एकबारगी सूचना है: यह STATUS_GUARD_PAGE_VIOLATION उठाता है और स्टैक वृद्धि जैसी चीज़ों के लिए प्रयुक्त होता है।8

सामान्य आलसी आवंटन, page-in, CoW, गार्ड सूचना और अंतिम पहुँच उल्लंघन CPU की दृष्टि से एक ही page-fault प्रवेश बिंदु पर इकट्ठा होते हैं। परिणाम तय करने वाला VAD, PTE, सुरक्षा गुण और पहुँच प्रकार का संयोजन है।

10. स्वयं देखें

अब तक का प्रवाह अपनी मशीन पर देखा जा सकता है। निम्नलिखित C++ प्रोग्राम 256MiB Reserve करता है, Commit करता है, हर पेज पर एक बाइट लिखता है, और अंत में Release करता है। हर चरण पर Enter की प्रतीक्षा करता है ताकि आप VMMap और PerfMon में बदलाव देख सकें।

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <psapi.h>

#include <cstdio>
#include <cstdlib>

#pragma comment(lib, "Psapi.lib")

constexpr SIZE_T kSize = 256ull * 1024 * 1024;

void PrintMemory(const char* stage)
{
    PROCESS_MEMORY_COUNTERS_EX c{};
    c.cb = sizeof(c);
    if (!GetProcessMemoryInfo(
            GetCurrentProcess(),
            reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&c),
            sizeof(c))) {
        std::printf("GetProcessMemoryInfo failed: %lu\n", GetLastError());
        return;
    }

    std::printf(
        "%-10s WS=%zu MiB  Private=%zu MiB  Faults=%lu\n",
        stage,
        c.WorkingSetSize / 1024 / 1024,
        c.PrivateUsage / 1024 / 1024,
        c.PageFaultCount);
}

void Pause(const char* message)
{
    PrintMemory(message);
    std::puts("Press Enter...");
    (void)std::getchar();
}

int main()
{
    SYSTEM_INFO si{};
    GetSystemInfo(&si);
    std::printf("PID=%lu, page=%lu bytes\n",
                GetCurrentProcessId(), si.dwPageSize);

    void* base = VirtualAlloc(nullptr, kSize, MEM_RESERVE, PAGE_NOACCESS);
    if (!base) {
        std::fprintf(stderr, "Reserve failed: %lu\n", GetLastError());
        return EXIT_FAILURE;
    }
    Pause("reserved");

    if (!VirtualAlloc(base, kSize, MEM_COMMIT, PAGE_READWRITE)) {
        std::fprintf(stderr, "Commit failed: %lu\n", GetLastError());
        VirtualFree(base, 0, MEM_RELEASE);
        return EXIT_FAILURE;
    }
    Pause("committed");

    auto* bytes = static_cast<volatile unsigned char*>(base);
    for (SIZE_T offset = 0; offset < kSize; offset += si.dwPageSize) {
        bytes[offset] = 1;
    }
    Pause("touched");

    if (!VirtualFree(base, 0, MEM_RELEASE)) {
        std::fprintf(stderr, "Release failed: %lu\n", GetLastError());
        return EXIT_FAILURE;
    }
    Pause("released");
}

Visual Studio के x64 Native Tools Command Prompt से निम्नलिखित आदेश से बनाया जा सकता है।

cl /std:c++20 /EHsc /W4 memory_fault_demo.cpp

10.1. VMMap में क्या देखें

VMMap वह उपकरण है जो आरक्षित आभासी मेमोरी, Commit, Working Set, Private और Shareable प्रकार के अनुसार दिखाता है।9 हर चरण पर अपेक्षित बदलाव ये हैं।

चरण अपेक्षित बदलाव
Reserve Address Space Size बढ़ता है, पर Commit/WS उतने नहीं
Commit Private Commit लगभग 256MiB बढ़ता है
Touch Working Set और Private WS काफी बढ़ते हैं, Fault Count भी बढ़ता है
Release लक्ष्य सीमा गायब होती है, और Commit तथा WS गिरते हैं

वास्तविक संख्याएँ रनटाइम, सुरक्षा उत्पादों, मेमोरी दबाव और देखने के समय से बदलती हैं। देखें चरणों के बीच संख्याएँ किस ओर गईं, यह नहीं कि ठीक 256MiB निकलीं या नहीं।

10.2. PerfMon में नरम और कठोर अलग करना

PerfMon में निम्नलिखित काउंटर उसी समय-अक्ष पर रखें।

  • Process(<target>)\\Page Faults/sec
  • Memory\\Pages Input/sec
  • Memory\\Page Reads/sec
  • Memory\\Available MBytes
  • Process(<target>)\\Working Set - Private
  • Process(<target>)\\Private Bytes

Process\\Page Faults/sec में soft और hard दोनों fault हैं। Memory\\Pages Input/sec दूसरी ओर hard fault सुलझाने के लिए डिस्क से पढ़े पेजों की संख्या है।10

इस प्रोग्राम के Touch चरण में Page Faults/sec कूदना चाहिए जबकि Pages Input/sec ज़्यादा नहीं बढ़ना चाहिए। नए Commit पेज demand-zero से साकार होते हैं, इसलिए डिस्क से मूल डेटा पढ़ने की ज़रूरत नहीं।

जब कई प्रक्रियाएँ एक नाम साझा करें, PerfMon संख्याएँ जैसे process#1 पुनरारंभ पर बदल सकती हैं। PID दिखाने वाले काउंटर से मिलाएँ, या Process V2 या ETW/WPA से PID से पहचानें।

11. व्यवहार में बचने योग्य तीन गलत पढ़त

11.1. «Commit बढ़ा, इसलिए RAM लीक है»

Commit रखने योग्य सामग्री की वादा की गई मात्रा है; न छुए पेज RAM में निवासी नहीं हो सकते। लीक आँकने के लिए Private Bytes की समय श्रृंखला, आवंटन का विवरण, और प्रसंस्करण समाप्त होने के बाद संख्या आधार रेखा पर लौटती है या नहीं देखें।

11.2. «Page Faults/sec ऊँचा है, इसलिए डिस्क धीमी है»

Soft fault में डिस्क I/O नहीं होता। Page Faults/sec, Pages Input/sec और स्टोरेज प्रतीक्षा अलग करें, और ज़रूरत हो तो ETW HardFault घटनाओं से स्रोत फ़ाइल और स्टैक का पीछा करें।

11.3. «Working Set खाली करने से लीक ठीक होगा»

Working Set से पेज निकालना Commit या स्वामित्व नहीं छोड़ता। पेज Standby या Modified में जाता है और बाद में फिर fault करके आता है। लीक ठीक करने के लिए आवंटक को VirtualFree, हीप मुक्त, ऑब्जेक्ट विनाश आदि करना चाहिए।

वह निकला भौतिक पेज कहाँ जाता है, हम भाग 2 में देखते हैं।

12. सार

  • MEM_RESERVE आभासी पता सीमा अलग रखता है पर RAM या पेज फ़ाइल में भौतिक क्षेत्र नहीं सौंपता।1
  • MEM_COMMIT Commit खर्च करता है और गारंटी देता है कि सामग्री भविष्य में रखी जा सकेगी, पर सामान्य भौतिक पेज पहली पहुँच तक नहीं सौंपा जाता।12
  • VAD सीमा खाता है, PTE आभासी-पेज खाता, और PFN डेटाबेस भौतिक-पेज खाता।
  • TLB miss page fault नहीं। यदि PTE मान्य है, केवल पेज-टेबल वॉक सुलझा देता है।
  • Demand-zero, Transition पुनर्स्थापना और साझा पेज जोड़ना soft fault हैं जो बिना डिस्क I/O सुलझ सकते हैं।5
  • यदि पेज फ़ाइल, DLL, EXE या मैप की गई फ़ाइल से पढ़ना चाहिए, वह hard fault है।6
  • यदि VAD, PTE और सुरक्षा गुण की जाँच fault न सुलझाए, आपको 0xC0000005 जैसा अपवाद मिलता है।7
  • प्रदर्शन फैसले के लिए केवल Page Faults/sec न देखें; उसी समय-अक्ष पर Pages Input/sec, Available, Working Set, Private Bytes और स्टोरेज प्रतीक्षा देखें।

जारी भाग 2, «एक भौतिक पेज का जीवन: पाँच सूचियाँ और पेज फ़ाइल की सच्चाई»।

Commit वादे के भौतिक पेज बनने के बाद, हम देखते हैं कि Working Set छोड़ने पर वह पेज कहाँ जाता है, PFN डेटाबेस और पेज सूचियों से।

संबंधित लेख

संबंधित परामर्श क्षेत्र

KomuraSoft LLC Windows अनुप्रयोग मेमोरी उपयोग, पहुँच उल्लंघन, स्टार्टअप देरी, पेजिंग और मूल कोड दोषों की जाँच संभालती है।

संदर्भ लिंक

  1. Microsoft Learn, VirtualAlloc function. इस पर कि MEM_RESERVE भौतिक भंडारण सौंपे बिना आभासी पता सीमा आरक्षित करता है; MEM_COMMIT सिस्टम की समग्र मेमोरी और पेज फ़ाइल के विरुद्ध commit चार्ज करता है; Commit पेज की प्रारंभिक सामग्री शून्य होती है; और वास्तविक भौतिक पेज पहुँच तक नहीं सौंपा जाता।  2 3 4 5 6

  2. Microsoft Learn, PERFORMANCE_INFORMATION structure. इस पर कि CommitTotal सिस्टम की वर्तमान Commit पेज संख्या है, और CommitLimit वह ऊपरी सीमा है जिसे पेज फ़ाइल बढ़ाए बिना Commit किया जा सकता है।  2

  3. Microsoft Learn, !vad (WinDbg). इस पर कि !vad VAD वृक्ष दिखाता है और आरंभ तथा अंत VPN, Commit, Mapped/Private, सुरक्षा गुण, Control Area और और भी देखने देता है। 

  4. Microsoft Learn, PageFault_TypeGroup1 class. इस पर कि ETW Transition Fault, Demand Zero Fault, Copy-on-Write, Guard Page Fault, Hard Page Fault और Access Violation अलग दर्ज करता है। 

  5. Microsoft Learn, Working Set. इस पर कि soft fault backing store पहुँचे बिना सुलझ सकता है, और दूसरे प्रक्रिया के Working Set, Transition, पहली-संदर्भ demand-zero आदि से होता है।  2 3

  6. Microsoft Learn, PageFault_HardFault class. इस पर कि HardFault घटना में FileObject, ReadOffset, ByteCount, VirtualAddress और थ्रेड ID होते हैं, जिससे पढ़ने स्रोत ट्रैक हो सकता है।  2

  7. Microsoft Learn, Access Violation C0000005. इस पर कि 0xC0000005 अमान्य मेमोरी पते के पढ़ने, लिखने या चलाने पर होता है, और अपवाद पैरामीटर पहुँच प्रकार तथा उल्लंघन पता बताते हैं।  2

  8. Microsoft Learn, Creating Guard Pages. इस पर कि PAGE_GUARD पेज पहुँच की एकबारगी सूचना देता है और STATUS_GUARD_PAGE_VIOLATION उठाता है। 

  9. Microsoft Learn, VMMap - Sysinternals. इस पर कि VMMap Commit आभासी मेमोरी को प्रकार से बाँटता है और हर प्रकार का Working Set तथा विस्तृत पता मानचित्र दिखाता है। 

  10. Microsoft Learn, Performance Analysis of Logs (PAL) Tool. इस पर कि Memory\\Pages Input/sec hard page fault सुलझाने के लिए डिस्क से पढ़े पेजों की संख्या है। 

निकटवर्ती विषयों में गहराई से जाने के लिए समान टैग वाले नवीनतम लेख।

Windows मेमोरी की गहराई (भाग 2) — भौतिक पेज का जीवन: पाँच सूचियाँ और पेज फ़ाइल की सच्चाई

यह लेख PFN डेटाबेस, Standby, Modified, मेमोरी संपीड़न और पेज फ़ाइल को जोड़कर बताता है कि Working Set छोड़ने के बाद भौतिक पेज कहाँ जाता है।

Windows मेमोरी की गहराई (भाग 3) — सेक्शन ऑब्जेक्ट और कॉपी-ऑन-राइट: DLL और फ़ाइल मैपिंग वास्तव में क्या हैं

यह लेख सेक्शन ऑब्जेक्ट, इमेज और डेटा मैपिंग, साझा कैश तथा कॉपी-ऑन-राइट को जोड़कर बताता है कि DLL और साझा मेमोरी भौतिक पृष्ठ कैसे साझा करत...

Windows वर्चुअलाइज़ेशन की गहराई (भाग 3) — सेकंडों में बूट होने वाली वर्चुअल मशीनें: WSL2, Windows Sandbox और कंटेनर इतने हल्के क्यों हैं

WSL2 और Windows Sandbox सेकंडों में शुरू होकर इतने हल्के क्यों लगते हैं? यह लेख डायनामिक बेस इमेज और डायरेक्ट मैप से डायनामिक मेमोरी आवंट...

Windows वर्चुअलाइज़ेशन की गहराई (भाग 2) — वह मेमोरी जिसे कर्नेल भी नहीं देख सकता: VBS, HVCI और Credential Guard कैसे काम करते हैं

संगत हार्डवेयर पर क्लीन इंस्टॉल पर VBS डिफ़ॉल्ट से सक्षम होता है और हाइपरवाइज़र तथा SLAT से कर्नेल से मज़बूत अलगाव बनाता है। यह लेख VTL, ...

Windows वर्चुअलाइज़ेशन की गहराई (भाग 1) — आपका Windows वास्तव में कहाँ चल रहा है? हाइपरवाइज़र और पार्टीशन

जब आप Hyper-V सक्षम करते हैं, तो होस्ट Windows स्वयं रूट पार्टीशन के रूप में हाइपरवाइज़र के ऊपर चलता है। यह लेख VT-x, SLAT और VMBus की भू...

ये पृष्ठ विषय को सेवाओं और निर्णयों के व्यापक संदर्भ में रखते हैं।

यह लेख निम्नलिखित सेवाओं से सीधे जुड़ा है।

अक्सर पूछे जाने वाले प्रश्न

इस लेख के विषय पर परामर्श में अक्सर पूछे जाने वाले प्रश्न।

VirtualAlloc को MEM_COMMIT देने से उसी क्षण RAM आवंटित हो जाती है?
सामान्य निजी मेमोरी में Commit सिस्टम की commit गुंजाइश खर्च करता है, पर संगत भौतिक पेज पहली पहुँच तक नहीं सौंपा जाता। लिखकर पहली बार छुए गए पेज को demand-zero fault के दौरान भौतिक पेज मिलता है।
क्या page fault का मतलब कुछ गलत है या प्रदर्शन समस्या है?
नहीं। बिना डिस्क I/O वाले soft fault — जैसे demand-zero या Standby से पेज लौटाना — सामान्य संचालन हैं। प्रदर्शन के फैसले के लिए केवल Page Faults/sec नहीं, Pages Input/sec, स्टोरेज प्रतीक्षा और Available MBytes भी देखें।
क्या TLB miss और page fault एक ही चीज़ हैं?
वे अलग हैं। भले TLB में अनुवाद न हो, यदि पेज टेबल की PTE मान्य है तो CPU केवल टेबल चलता है और अनुवाद फिर दर्ज करता है। जब PTE अमान्य हो या सुरक्षा उल्लंघन हो तब यह page-fault प्रवेश बिंदु पर जाता है।
यदि पता सीमा VAD में है तो पहुँच उल्लंघन नहीं हो सकता?
ज़रूरी नहीं। VAD होने के अलावा मेमोरी प्रबंधक Reserve बनाम Commit, पढ़ना/लिखना/चलाना सुरक्षा, गार्ड पेज, PTE स्थिति और और भी बातें आँकता है। यदि fault सुलझ न सके तो आपको 0xC0000005 जैसा अपवाद मिलता है।
ऊँचा Page Faults/sec मतलब सिस्टम में RAM कम है?
केवल इससे नहीं पता चलता। Page Faults/sec में बहुत से soft fault भी शामिल हैं। इसे उसी समय-अक्ष पर Memory\Pages Input/sec, Memory\Page Reads/sec, Available MBytes और डिस्क प्रतीक्षा समय से जोड़ना चाहिए।

लेखक की प्रोफ़ाइल

लेख के लेखक का परिचय पृष्ठ।

Go Komura

KomuraSoft LLC के प्रतिनिधि

Windows सॉफ़्टवेयर विकास, तकनीकी परामर्श और बग जाँच में विशेषज्ञ, विशेष रूप से मौजूदा सिस्टम वाली परियोजनाओं और पुनरुत्पादन में कठिन बग में।

सार्वजनिक लिंक

ब्लॉग पर लौटें