Windows मेमोरी की गहराई (भाग 3) — Section object और copy-on-write: DLL और file mapping वास्तव में क्या हैं

· अद्यतन तिथि: · · Windows, मेमोरी प्रबंधन, shared memory, file mapping, copy-on-write, DLL, Cache Manager

संशोधन इतिहास (पहला संस्करण, 20 Aug 2026 को प्रकाशित)
पहला प्रकाशन
इस लेख का हवाला दें(DOI: 10.5281/zenodo.22176182)

यह लेख Zenodo पर संग्रहीत है। नीचे वह DOI है जो हमेशा नवीनतम संस्करण की ओर ले जाता है, और वह DOI भी जो आपके पढ़े जा रहे संस्करण से बँधा है।

Go Komura (2026). Windows मेमोरी की गहराई (भाग 3) — Section object और copy-on-write: DLL और file mapping वास्तव में क्या हैं. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22176182 https://comcomponent.com/hi/blog/windows-memory-internals-section-copy-on-write/

DOI (नवीनतम संस्करण)
10.5281/zenodo.22176182
DOI (यह संस्करण)
10.5281/zenodo.22176183

पिछले लेख «Windows मेमोरी की गहराई (भाग 2) — एक physical page का जीवन» में हमने देखा कि Working Set छोड़ने वाला physical page Modified, Standby, Free और Zeroed से कैसे गुज़रता है। उसी Standby में DLL, EXE, mapped फ़ाइलें और file cache के pages भी रहते हैं।

यहाँ एक प्रश्न उठता है। जब 100 processes एक ही kernel32.dll इस्तेमाल करते हैं, क्या Windows RAM में code pages के 100 सेट रखता है? जब दो processes एक ही फ़ाइल को memory-map करते हैं, क्या दूसरा उस page का उपयोग कर सकता है जिसे एक ने पढ़ा?

उत्तर है कई virtual addresses को एक ही physical page पर map करना। उस sharing इकाई का केंद्र section object है, और लिखने के समय ही sharing तोड़ने वाला mechanism copy-on-write (Copy-on-Write, CoW) है।

यह लेख देखता है कि EXE और DLL, data फ़ाइलें, pagefile-backed shared memory और file cache एक ही file stream से कैसे जुड़ते हैं, और processing path कहाँ बँटते हैं। संख्याएँ पढ़ना स्वयं परिचयात्मक लेख «What Does Windows’ “Memory Usage” Actually Mean?» को आधार मानता है।

«Windows मेमोरी की गहराई» — तीनों भाग

  1. भाग 1: Virtual addresses और page fault
    हम उस क्षण का अनुसरण करते हैं जब Commit किया गया virtual page physical RAM पाता है।
  2. भाग 2: एक physical page का जीवन
    हम Working Set छोड़ने वाले page की state-changes का अनुसरण करते हैं।
  3. भाग 3 (यह लेख): Section object और copy-on-write
    हम उस mechanism का अनुसरण करते हैं जिससे DLL, file mapping और shared memory physical pages share करते हैं।

भाग 3 जिस प्रश्न का उत्तर देता है वह केवल एक है।

कई processes एक ही DLL या फ़ाइल को physical pages के एक सेट के रूप में क्यों इस्तेमाल कर सकते हैं?

लक्षित पाठक वे developers और operators हैं जो DLL sharing, CreateFileMapping, MapViewOfFile, shared memory, CoW और file cache से संबंध को केवल API उपयोग नहीं बल्कि internal structure से समझना चाहते हैं। पूर्वापेक्षाएँ Windows 10/11 या वर्तमान Windows Server हैं, और आवश्यक background virtual addresses, page fault और Working Set की बुनियाद है। कठिनाई मध्यम है; हम Control Area और Prototype PTE जैसे internal शब्द भी इस्तेमाल करते हैं, लेकिन अवलोकन VMMap, Process Explorer और QueryWorkingSetEx से दोहराए जा सकते हैं।

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

शुरुआत में पूरी तस्वीर।

  • Section object share करने योग्य memory range दर्शाता है।
    हर process उस section का भाग अपने virtual space में «view» के रूप में map करता है।1
  • एक ही section के views एक ही virtual address पर होने आवश्यक नहीं।
    Process A का 0x000001... और process B का 0x000002... एक ही section offset और एक ही physical page की ओर इशारा कर सकते हैं।2
  • File-backed और pagefile-backed sections होते हैं।
    पहले वास्तविक फ़ाइल इस्तेमाल करते हैं; दूसरे स्पष्ट फ़ाइल के बिना shared memory आदि के लिए।2
  • EXE/DLL load करना image section है; साधारण file mapping data section है।
    SEC_IMAGE के साथ PE के अंदर section attributes page protection तय करते हैं।3
  • पढ़ते समय एक ही physical page share हो सकता है।
    जब एक पक्ष CoW page पर लिखता है, केवल वही page कॉपी होता है और लिखने वाले process का PTE बदल जाता है।4
  • एक ही file stream पर भी cache, data और image paths अलग होते हैं।
    Cache Manager का cached I/O SharedCacheMap इस्तेमाल करता है, data mapping DataSectionObject, और EXE/DLL ImageSectionObject। तीनों SECTION_OBJECT_POINTERS से एक ही stream से जुड़ते हैं, लेकिन image fault Cache Manager से नहीं जाता।5
  • अकेले Private Bytes यह पुष्टि नहीं कर सकते कि CoW हुआ।
    FILE_MAP_COPY map के समय पूरे view का Commit पहले ही लगाता है, इस आशंका से कि बाद में हर page private हो जाए। Per-page जाँच के लिए QueryWorkingSetEx का Shared bit इस्तेमाल करें।67

एक वाक्य में: Share virtual address नहीं, बल्कि section के अंदर की content और उस क्षण का matching physical page है।

2. Section object और view

Microsoft की परिभाषा में section object share करने योग्य memory क्षेत्र दर्शाता है और वह mechanism भी है जो फ़ाइल को process के address space में map करता है।1

समझने की कुंजी section को उस view से अलग करना है जो हर process देखता है।

अवधारणा भूमिका
Section object Share करने की content, आकार, backing store और protection की ऊपरी सीमा दर्शाता है
View Section का भाग किसी process में virtual address range के रूप में दिखाता है
PTE View के हर virtual page को वर्तमान physical page या unrealized अवस्था से बाँधता है
PFN वह physical page दर्शाता है जो वास्तव में RAM में मौजूद है

Win32 में CreateFileMapping file-mapping object का handle लौटाता है, और MapViewOfFile process के virtual space में view बनाता है।3

HANDLE mapping = CreateFileMappingW(
    file,
    nullptr,
    PAGE_READONLY,
    0,
    0,
    nullptr);

void* view = MapViewOfFile(
    mapping,
    FILE_MAP_READ,
    0,
    0,
    0);

केवल CreateFileMapping बुलाने से process को पढ़ने योग्य address अभी नहीं मिलता। View बनाना भी हर page तुरंत RAM में नहीं डालता। पहले छुए गए page से page fault फ़ाइल content पढ़ता है और PTE से physical page बाँधता है।8 अर्थात् भाग 1 का demand paging section view पर भी लागू होता है।

2.1. एक ही section, अलग virtual addresses

भले process A और process B एक ही section का एक ही offset map करें, view का प्रारंभ address भिन्न हो सकता है।

अलग virtual addresses को एक ही physical page पर map करनाProcess A और process B प्रत्येक के पास अलग virtual address पर view है, लेकिन वे एक ही section offset से एक ही physical page PFN X तक पहुँचते हैंProcess A: 0x000001A00000 + 0x3000Section offset 0x3000Process B: 0x000002700000 + 0x3000एक ही physical page PFN X

चित्र 1: Share section के अंदर की content और physical page है, virtual address नहीं।

इसीलिए shared memory में raw pointer न रखें। Process A का pointer मान process B में unrelated address हो सकता है।

Shared structure में view के प्रारंभ से offset, fixed-width integers, तथा स्पष्ट version और alignment इस्तेमाल करें। Microsoft का MapViewOfFileEx document भी pointers के बजाय base से offsets रखने की सलाह देता है, क्योंकि भविष्य में वही address उपलब्ध रहे इसकी गारंटी नहीं।6

3. File-backed और pagefile-backed

Sections इस आधार पर दो बड़े प्रकारों में बँटते हैं कि content कहाँ से restore हो सकती है।

File-backed और pagefile-backed कैसे बँटते हैंCreateFileMapping को वास्तविक फ़ाइल देने से file-backed section बनता है, और clean page मूल फ़ाइल से फिर पढ़ा जा सकता है। INVALID_HANDLE_VALUE देने से pagefile-backed section बनता है; page file content थामती है, जो object नष्ट होने पर गायब हो जाती हैवास्तविक फ़ाइल handle देंINVALID_HANDLE_VALUE देंCreateFileMappingFile-backed sectionPagefile-backed sectionClean page मूल फ़ाइल से फिर पढ़ा जा सकता हैPage file content थामती है, जो नष्ट होने पर गायब होती है

चित्र 2: Backing store का अंतर तय करता है कि content कहाँ से लौटे और कितनी देर जिए।

3.1. File-backed section

CreateFileMapping को वास्तविक फ़ाइल देने से file-backed section बनता है।

  • Read-only view आवश्यक pages फ़ाइल से पढ़ता है।
  • Read/write view के बदलाव उस फ़ाइल के data माने जाते हैं।
  • CoW view के बदलाव मूल फ़ाइल में नहीं लिखे जाते; वे private pages बन जाते हैं।

अगर file-backed page clean है, physical page त्यागा जा सकता है और मूल फ़ाइल से फिर पढ़ा जा सकता है। यही गुण भाग 2 में देखी Standby और file cache की दक्षता थामता है।

3.2. Pagefile-backed section

CreateFileMapping के hFile में INVALID_HANDLE_VALUE देना और आकार बताना pagefile-backed section बनाता है।

HANDLE mapping = CreateFileMappingW(
    INVALID_HANDLE_VALUE,
    nullptr,
    PAGE_READWRITE,
    0,
    64 * 1024,
    L"Local\\KomuraMemoryDemo");

यह स्पष्ट data फ़ाइल के बिना section है, जिसे page file थामती है। प्रारंभिक content शून्य है, और कई processes नाम, handle inheritance, DuplicateHandle आदि से एक ही object खोल सकते हैं।93 बदलाव उसी shared page को map करने वाले processes को दिखते हैं। दूसरी ओर, section object नष्ट होने पर content नहीं रहती, इसलिए स्थायी फ़ाइल छोड़ने के लिए उपयुक्त नहीं।2

सावधानी: Shared memory अपने आप mutual exclusion नहीं लाती। Mutex, semaphore, event, lock-free protocol आदि अलग से डिज़ाइन करें।9

4. Image mapping और data mapping

जब हम कहते हैं «EXE या DLL भी file mapping है», साधारण data फ़ाइल से अंतर फिर भी रखना चाहिए।

मद Image mapping Data mapping
मुख्य उपयोग EXE या DLL load करना साधारण फ़ाइलें, shared data
निर्माण विशेषता SEC_IMAGE PAGE_READONLY, PAGE_READWRITE आदि
Page protection PE image के अंदर attributes तय करती हैं Mapping और view specification तय करते हैं
लेखन Writable section या CoW से private किया जा सकता है Shared write या CoW चुना जा सकता है
VirtualQuery Type MEM_IMAGE MEM_MAPPED

SEC_IMAGE के साथ view की page protection मुख्यतः executed image की अपनी section attributes तय करती हैं, न कि CreateFileMapping को दिए साधारण protection मान।3

इस mechanism से code जैसे unmodified pages कई processes में एक ही physical page share कर सकते हैं, और केवल process-private बदलाव वाले pages CoW से शाखा लेते हैं। फिर भी हर DLL page आवश्यक रूप से share नहीं होता — ASLR relocation, loader fixes, hotpatch, वास्तविक PE section attributes आदि के कारण।

महत्वपूर्ण डिज़ाइन है पहले share करने योग्य pages share करें, और केवल बदलाव वाले pages देर से कॉपी करें।

5. Copy-on-write शुरू से अंत तक

दो processes एक ही CoW page पढ़ रहे हों, उस अवस्था से process A के एक byte लिखने तक चलें।

5.1. लिखने से पहले

लेखन होने से पहले दोनों processes के PTE अवधारणात्मक रूप से एक ही shared page तक पहुँचते हैं, और पठन वैसे ही सफल होता है।

Copy-on-write से पहले की shared अवस्थालेखन होने से पहले process A का PTE और process B का PTE दोनों एक ही shared page PFN X तक पहुँचते हैं, और पठन वैसे ही सफल होता हैProcess A PTEShared PFN X(read / copy-on-write)Process B PTE

चित्र 3: लिखने से पहले दोनों processes के PTE एक ही physical page की ओर इशारा करते हैं।

5.2. लिखते समय protection fault

CoW page शुरू से साधारण shared writable page नहीं होता। जब process A लिखने का प्रयास करता है, CPU protection fault उठाता है। नियंत्रण पाने वाला memory manager तय करता है कि यह अवैध लेखन नहीं बल्कि CoW attribute पर लेखन है।

5.3. नया physical page बनाना

उस निर्णय पर Windows यह करता है।

  1. Process A के लिए एक physical page प्राप्त करें।
  2. PFN X की content नए page PFN Y पर कॉपी करें।
  3. Process A का PTE PFN Y से बदलें।
  4. Process A की protection साधारण read/write करें।
  5. असफल लिखने के instruction को फिर चलाएँ।
Copy-on-write के बाद की विभाजित अवस्थाProcess A की लेखन के बाद केवल process A का PTE उस private page PFN Y से बदला जाता है जिसे content की कॉपी मिली, जबकि process B का PTE मूल shared page PFN X की ओर इशारा करता रहता हैलिखते समय कॉपीProcess A PTEPrivate PFN Y(R/W, लिखने के बाद)Process B PTEShared PFN X(मूल)

चित्र 4: केवल लिखने वाले process का PTE नए private page से बदला जाता है; दूसरा पक्ष मूल content पढ़ता रहता है।

Process B मूल content पढ़ता रहता है और process A का बदलाव नहीं देखता। यही Copy-on-Write है। DLL sharing और FILE_MAP_COPY एक ही सिद्धांत इस्तेमाल करते हैं: जब तक लिखें नहीं, कॉपी न करें।46

5.4. FILE_MAP_WRITE से अंतर

FILE_MAP_WRITE की shared लिखत से लिखा page इस तरह डिज़ाइन है कि एक पक्ष का बदलाव उसी file mapping वाले दूसरे view से भी दिखे। FILE_MAP_COPY में इसके विपरीत केवल लिखे गए pages process-private होते हैं; बदलाव मूल फ़ाइल में वापस नहीं लिखे जाते और view unmap होते ही खो जाते हैं।6

क्या आप चाहते हैं «shared memory से update पहुँचाना», या «हर process shared प्रारंभिक data से private बदलाव करे»? उद्देश्य के अनुसार सही चुनाव उलटा होता है।

6. CoW के बाद भी MEM_MAPPED / MEM_IMAGE

CoW के बाद page physically Private हो चुका है। तब लगता है VirtualQuery का Type भी MEM_PRIVATE हो जाएगा, लेकिन वास्तव में data view MEM_MAPPED और executable image MEM_IMAGE रहता है। VirtualQuery बताता है कि क्षेत्र किस प्रारंभिक allocation से आया।7

Per page यह देखने के लिए कि CoW पहले ही हुआ या नहीं, यह procedure इस्तेमाल करें।

  1. Target page तक पहुँचें और उसे resident बनाएँ।
  2. QueryWorkingSetEx से page की Working Set जानकारी लें।
  3. Shared bit देखें।
  4. अगर Shared == 0 तो वह resident page Private है।

VMMap में पुष्टि करते समय भी केवल क्षेत्र के Type नहीं, Working Set के Private/Shareable विभाजन देखें।

6.1. Private Bytes बढ़ें नहीं भी सकते

FILE_MAP_COPY में process बाद में view के हर page पर लिख सकता है। इसलिए Windows map के समय पूरे view के बराबर Commit charge लेता है।6 परिणामस्वरूप पहला page लिखने पर उसी क्षण Private Bytes 4KiB नहीं बढ़ सकते।

CoW देखते समय ये metrics प्राथमिकता दें।

  • QueryWorkingSetEx का Shared bit
  • VMMap का Private WS / Shareable WS
  • RAMMap की physical-page जानकारी
  • पूरक जानकारी के रूप में Private Bytes

अगर «लिखने के क्षण Private Bytes बढ़े या नहीं» को pass/fail परीक्षा मानें, तो सही काम कर रहे CoW छूट जाएँगे।

7. Cache Manager से संपर्क — तीन paths अलग रखें

«EXE/DLL load, file cache और shared memory सब sections हैं» कहना पूरी तस्वीर देता है, लेकिन implementation को एक object में न समेटें।

File stream के पास SECTION_OBJECT_POINTERS होते हैं, जिन्हें memory manager और Cache Manager इस्तेमाल करते हैं।

typedef struct _SECTION_OBJECT_POINTERS {
    PVOID DataSectionObject;
    PVOID SharedCacheMap;
    PVOID ImageSectionObject;
} SECTION_OBJECT_POINTERS;
  • DataSectionObject: Data फ़ाइल की section अवस्था
  • SharedCacheMap: Cache Manager द्वारा track किया गया cache view
  • ImageSectionObject: Executable image की section अवस्था

Microsoft document बताता है कि यह structure file object को file stream के section से बाँधती है और memory में content तथा cache जानकारी track करती है।5

यहाँ I/O श्रृंखला और memory श्रृंखला मिलती हैं। फिर भी तीन paths अलग समझें।

  • Cached ReadFile / WriteFile Cache Manager के SharedCacheMap और cache view इस्तेमाल करते हैं।
  • Data फ़ाइल पर mapping fault memory manager DataSectionObject पक्ष पर संभालता है। वह उसी stream के cached I/O से सहयोग कर content consistent रखता है।
  • EXE/DLL पर image fault memory manager ImageSectionObject और paging I/O से संभालता है। यह Cache Manager के SharedCacheMap से जाने वाला path नहीं।
एक ही file stream से जुड़ने वाले तीन pathsCached ReadFile/WriteFile SharedCacheMap इस्तेमाल करते हैं, data-mapping fault DataSectionObject, और EXE/DLL image fault ImageSectionObject; तीनों SECTION_OBJECT_POINTERS से एक ही file stream से जुड़ते हैंCached ReadFile / WriteFileSharedCacheMapData-mapping faultDataSectionObjectEXE/DLL image faultImageSectionObjectएक ही file stream(SECTION_OBJECT_POINTERS)

चित्र 5: तीन paths अलग process होते हैं, लेकिन एक ही file stream से जुड़ते हैं।

तीनों में समान यह नहीं कि «सब Cache Manager में जाता है», बल्कि यह कि एक ही file stream cache, data section और image section जैसी अलग अवस्थाएँ SECTION_OBJECT_POINTERS से बाँधती है।5 Cache read-write, Lazy Writer, तथा Cc और Mm का संबंध «The Depths of Windows I/O (Part 4) — Cache Manager: When Does Your WriteFile Actually Reach the Disk?» में है।

ध्यान दें कि memory-mapped view को ReadFile/WriteFile से मिलाएँ तो हमेशा एक ही क्षण की content दिखने की गारंटी नहीं। डिज़ाइन में synchronization, flush और file-share mode होना चाहिए।36

8. Object और view का lifetime

केवल CreateFileMapping handle बंद करने से मौजूदा view नष्ट नहीं होता। View section का internal reference रखता है, और हर view के UnmapViewOfFile तथा हर handle के CloseHandle के बाद ही object नष्ट योग्य होता है।3

UnmapViewOfFile(view);
CloseHandle(mapping);
CloseHandle(file);

Lifetime का यह अलगाव «फ़ाइल बंद कर दी, फिर भी उपयोग में है» घटना का कारण है। File handle बंद करने के बाद भी अगर image section या data view file stream का reference रखे, फ़ाइल का अंतिम close बाद में आता है।

I/O पक्ष की cleanup/close से संबंध «The Depths of Windows I/O (Part 1)» में है, और implementation जाल «Shared Memory Pitfalls and Practical Best Practices» में।

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

9.1. दो processes से एक ही DLL देखना

पहले मौजूदा processes से DLL sharing पुष्टि करें।

  1. Administrator के रूप में Process Explorer शुरू करें।
  2. दो cmd.exe processes शुरू करें।
  3. View > Lower Pane View > DLLs चुनें।
  4. दोनों processes में एक ही DLL का path और mapping पुष्टि करें।
  5. VMMap में प्रत्येक cmd.exe खोलें और Images Working Set, Private तथा Shareable तुलना करें।

Process Explorer में एक ही DLL दिखना प्रमाण है कि दोनों ने एक ही image map की। अकेले इससे यह सिद्ध नहीं होता कि हर page का PFN मेल खाता है। Per-page sharing पुष्टि के लिए VMMap का Shareable विभाजन, RAMMap और QueryWorkingSetEx मिलाएँ। Process Explorer और VMMap Sysinternals देते हैं।1011

9.2. दो processes से FILE_MAP_COPY देखना

निम्न प्रोग्राम एक ही फ़ाइल को CoW view के रूप में map करता है और QueryWorkingSetEx का Shared bit दिखाता है। File-mapping object PAGE_READONLY से बनता है, लेकिन वह protection FILE_MAP_COPY view से compatible है, और view पक्ष की पहली लेखन CoW पैदा करती है।3

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

#include <cstdio>
#include <cwchar>

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

void PrintPage(const char* stage, void* address)
{
    MEMORY_BASIC_INFORMATION mbi{};
    if (!VirtualQuery(address, &mbi, sizeof(mbi))) {
        std::printf("VirtualQuery failed: %lu\n", GetLastError());
        return;
    }

    for (int attempt = 0; attempt < 3; ++attempt) {
        // The page may have been trimmed while the user was waiting.
        // Touch it immediately before querying the working-set attributes.
        volatile unsigned char resident =
            *static_cast<volatile unsigned char*>(address);
        (void)resident;

        PSAPI_WORKING_SET_EX_INFORMATION ws{};
        ws.VirtualAddress = address;
        if (!QueryWorkingSetEx(GetCurrentProcess(), &ws, sizeof(ws))) {
            std::printf("QueryWorkingSetEx failed: %lu\n", GetLastError());
            return;
        }

        if (!ws.VirtualAttributes.Valid) {
            Sleep(0);
            continue;
        }

        std::printf(
            "%s: Type=0x%lx Valid=1 Shared=%llu ShareCount=%llu\n",
            stage,
            static_cast<unsigned long>(mbi.Type),
            static_cast<unsigned long long>(ws.VirtualAttributes.Shared),
            static_cast<unsigned long long>(ws.VirtualAttributes.ShareCount));
        return;
    }

    std::printf(
        "%s: page is not resident; Shared/ShareCount were not interpreted\n",
        stage);
}

int wmain(int argc, wchar_t** argv)
{
    if (argc != 3) {
        std::fwprintf(stderr, L"usage: cow_demo <file> <read|write>\n");
        return 2;
    }

    HANDLE file = CreateFileW(
        argv[1], GENERIC_READ, FILE_SHARE_READ,
        nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
    if (file == INVALID_HANDLE_VALUE) return 3;

    HANDLE mapping = CreateFileMappingW(
        file, nullptr, PAGE_READONLY, 0, 0, nullptr);
    if (!mapping) {
        CloseHandle(file);
        return 4;
    }

    auto* view = static_cast<unsigned char*>(
        MapViewOfFile(mapping, FILE_MAP_COPY, 0, 0, 0));
    if (!view) {
        CloseHandle(mapping);
        CloseHandle(file);
        return 5;
    }

    volatile unsigned char value = view[0];
    (void)value;

    std::puts("Start the other process. When both are waiting, press Enter...");
    (void)std::getchar();
    PrintPage("before", view);

    if (std::wcscmp(argv[2], L"write") == 0) {
        std::puts("Press Enter to trigger copy-on-write...");
        (void)std::getchar();
        view[0] ^= 0x5a;
        PrintPage("after write", view);
    } else {
        std::puts("After the writer changes its page, press Enter...");
        (void)std::getchar();
        PrintPage("reader after peer write", view);
    }

    std::puts("Press Enter to exit...");
    (void)std::getchar();

    UnmapViewOfFile(view);
    CloseHandle(mapping);
    CloseHandle(file);
}

बनाएँ और तैयार करें।

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

$path = "$env:TEMP\\cow-demo.bin"
[IO.File]::WriteAllBytes($path, [byte[]]::new(65536))

फिर दो consoles से एक ही फ़ाइल खोलें।

.\\cow_demo.exe "$env:TEMP\\cow-demo.bin" read
.\\cow_demo.exe "$env:TEMP\\cow-demo.bin" write

दोनों शुरू करने के बाद पहले read पक्ष फिर write पक्ष पर Enter दबाएँ, और पुष्टि करें कि दोनों के before में Shared set है। Write पक्ष पर फिर Enter दबाएँ तो उस process का page Shared 0 हो जाता है। फिर read पक्ष पर Enter दबाएँ और पुष्टि करें कि पाठक मूल page पढ़ता रहता है। लिखने के बाद भी VirtualQuery का Type MEM_MAPPED रहता है।

ध्यान दें कि PrintPage पूछने से ठीक पहले target page को फिर छूता है, और Valid == 0 हो तो Shared तथा ShareCount की व्याख्या नहीं करता और तीन बार तक retry करता है। अगर page अभी भी resident नहीं तो परिणाम नहीं देता और यह बताता है। ShareCount समय और memory pressure से बदल सकता है, इसलिए Valid == 1 पर पुष्ट Shared bit का बदलाव देखें, कोई स्थिर मान नहीं।

10. व्यवहार में बचने योग्य पाँच गलत पाठ

10.1. «Shared memory एक ही virtual address पर पहुँचती है»

Share section और physical page है। View का virtual address process के अनुसार भिन्न हो सकता है, इसलिए raw pointers के बजाय offsets रखें।

10.2. «अगर वही DLL है तो हर page आवश्यक रूप से share है»

Clean code pages share करना आसान है, जबकि relocation, writable sections, CoW और माप के क्षण की residency भी Private pages पैदा करते हैं।

10.3. «CoW के बाद यह MEM_PRIVATE हो जाता है»

VirtualQuery का Type MEM_MAPPED या MEM_IMAGE रहता है। वास्तविक sharing QueryWorkingSetEx से पुष्टि करें।7

10.4. «अगर Private Bytes नहीं बढ़े तो CoW नहीं हुआ»

FILE_MAP_COPY पूरे view का Commit पहले लगाता है। Private WS और Shared bit प्राथमिकता दें।6

10.5. «अगर page share है तो synchronization अनावश्यक है»

एक ही physical page देखना और कई CPU cores से सुरक्षित update करना अलग समस्याएँ हैं। Atomicity, memory order, mutual exclusion, crash के समय mid-state, और version compatibility डिज़ाइन करें।

Reference और lifetime को अलग-अलग अनुसरण करने का विचार Excel COM interop के बाद बचे processes की समस्या पर भी लागू होता है। देखें «Why EXCEL.EXE Processes Remain After C# Excel COM Automation — Reference Release Patterns and the Replacement Decision»।

11. सार

  • Section object share करने योग्य memory range दर्शाता है, और हर process उसे अपने virtual space में view के रूप में map करता है।1
  • एक ही section का एक ही offset अलग virtual addresses से एक ही physical page पर map होता है।2
  • File-backed section वास्तविक फ़ाइल थामता है; pagefile-backed section named shared memory आदि थामता है।9
  • EXE/DLL image section और साधारण फ़ाइल data section मानी जाती है; protection और वापस लिखने का गंतव्य भिन्न हैं।3
  • CoW पठन के दौरान physical page share करता है और पहली लेखन पर केवल वही page कॉपी कर PTE बदलता है।4
  • CoW के बाद भी VirtualQuery MEM_MAPPED/MEM_IMAGE लौटाता है, इसलिए QueryWorkingSetEx के Shared bit से पुष्टि करें।7
  • FILE_MAP_COPY में पूरे view का Commit पहले लगता है, इसलिए अकेले Private Bytes से CoW नहीं आँका जा सकता।6
  • Cache Manager का cached I/O, data mapping और image mapping एक ही file stream से अलग paths के रूप में जुड़ते हैं जो क्रमशः SharedCacheMap, DataSectionObject और ImageSectionObject इस्तेमाल करते हैं।5
  • Shared memory तभी सुरक्षित होती है जब view और handle का lifetime, synchronization, ACL और offset डिज़ाइन शामिल हों।

इससे «Windows मेमोरी की गहराई» के तीनों भाग पूरे होते हैं। आप virtual address Reserve/Commit करते हैं, page fault से physical page पाते हैं, page को Working Set से page list पर ले जाते हैं, section से share करते हैं, और केवल लिखे pages CoW से बाँटते हैं — Windows memory management इसी एक flow से जुड़ा है।

संबंधित लेख

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

KomuraSoft LLC Windows applications की shared memory, file mapping, DLL loading, file locking, inter-process communication और memory उपयोग की दोष जाँच संभालती है।

संदर्भ लिंक

  1. Microsoft Learn, Section Objects and Views. Section object के share करने योग्य memory range दर्शाने, और हर process के section का भाग view के रूप में map करने पर। ↩ ↩2 ↩3

  2. Microsoft Learn, File-Backed and Page-File-Backed Sections. File-backed और pagefile-backed sections, CoW, तथा अलग processes के virtual addresses से एक ही physical memory share करने पर। ↩ ↩2 ↩3 ↩4

  3. Microsoft Learn, CreateFileMappingW function. File-mapping object, pagefile-backed section, SEC_IMAGE, view और handle का lifetime, तथा एक ही फ़ाइल थामने वाले views की consistency पर। ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  4. Microsoft Learn, Memory Protection. कई processes के एक ही DLL के physical pages share करने, और एक पक्ष के लिखने पर CoW के नए physical page पर कॉपी कर PTE update करने पर। ↩ ↩2 ↩3

  5. Microsoft Learn, SECTION_OBJECT_POINTERS structure. DataSectionObject, SharedCacheMap और ImageSectionObject के file stream mapping तथा cache जानकारी को memory manager / Cache Manager से बाँधने पर। ↩ ↩2 ↩3 ↩4

  6. Microsoft Learn, MapViewOfFileEx function. FILE_MAP_COPY के साथ CoW; page file से backed private pages; पूरे view का Commit charge; तथा virtual address के बजाय offset रखने पर। ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  7. Microsoft Learn, VirtualQuery function. CoW के बाद Type के MEM_MAPPED/MEM_IMAGE रहने, तथा QueryWorkingSetEx के Shared bit से privatization पुष्टि पर। ↩ ↩2 ↩3 ↩4

  8. Microsoft Learn, Managing Memory Sections. View तक पहुँचने तक physical memory न दिए जाने, और पहली पहुँच के page fault के फ़ाइल content पढ़ने पर। ↩

  9. Microsoft Learn, Sharing Files and Memory. नाम या handle से एक ही file-mapping object share करने; INVALID_HANDLE_VALUE से pagefile-backed shared memory बनाने; तथा synchronization अलग आवश्यक होने पर। ↩ ↩2 ↩3

  10. Microsoft Learn, Process Explorer - Sysinternals. Process Explorer के process handles तथा loaded DLL / memory-mapped फ़ाइलें दिखाने पर। ↩

  11. Microsoft Learn, VMMap - Sysinternals. VMMap के process virtual memory को Image, Mapped File, Private आदि में बाँटने, तथा Working Set का Private/Shareable विभाजन दिखाने पर। ↩

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

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

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

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

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

क्या एक ही DLL इस्तेमाल करने वाला हर process RAM में उस DLL की पूरी कॉपी पाता है?
आमतौर पर नहीं। उसी image के unmodified pages हर process के अलग virtual addresses से एक ही physical page पर map होते हैं। केवल वे pages जिन्हें लिखना हो, copy-on-write आदि से process-private physical pages बनते हैं।
क्या CreateFileMapping उसी क्षण process को memory allocate करता है?
CreateFileMapping file-mapping object बनाता है, लेकिन उसे process के virtual space में दिखाने वाला MapViewOfFile है। इसके अलावा view के physical pages आमतौर पर पहली बार छुए गए page से page fault द्वारा साकार होते हैं।
FILE_MAP_WRITE और FILE_MAP_COPY में क्या अंतर है?
FILE_MAP_WRITE के ज़रिए बदलाव shared file-data पक्ष पर दिखने वाली लिखत है। FILE_MAP_COPY प्रारंभिक pages share करता है, लेकिन केवल लिखे गए pages process-private कॉपी बनते हैं; बदलाव मूल फ़ाइल में वापस नहीं लिखे जाते और view unmap होते ही खो जाते हैं।
Copy-on-write के बाद क्या VirtualQuery MEM_PRIVATE लौटाता है?
नहीं। Data view MEM_MAPPED और image view MEM_IMAGE रहता है। यह देखने के लिए कि page वास्तव में private हुआ या नहीं, page को resident बनाएँ और QueryWorkingSetEx का Shared bit देखें।
क्या shared memory में raw pointer रखना चाहिए?
आमतौर पर नहीं। एक ही section होने पर भी कोई गारंटी नहीं कि हर process का view एक ही virtual address पर होगा। Shared structure में base से offset, fixed-width integers, तथा स्पष्ट layout और synchronization योजना इस्तेमाल करें।

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

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

Go Komura

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

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

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

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