2011-09-21 8 views
7

मैं एमएस विंडो के वर्चुअलअलोक द्वारा आवंटित स्मृति के क्षेत्र का आकार बदलना चाहता हूं। वर्चुअलफ्री दस्तावेज़ीकरण को देखते हुए, केवल एक आंशिक रूप से एक क्षेत्र को कम करना संभव है, लेकिन आंशिक रूप से इसे रिलीज़ करना संभव नहीं है। यही है, भौतिक स्मृति का हिस्सा जारी करना संभव है, लेकिन वर्चुअल मेमोरी का हिस्सा नहीं है।वर्चुअलअलोक द्वारा आवंटित क्षेत्रों का आकार कैसे बदलें?

मुझे पता है कि इस तरह के मामले में इस क्षेत्र को पुन: आवंटित करना आवश्यक हो सकता है। हालांकि, पूरे क्षेत्र में प्रतिलिपि बल्कि अक्षम होगी। क्या एक अलग आकार के साथ एक नया क्षेत्र आवंटित करने के लिए खिड़कियों से पूछने का कोई तरीका है, जो एक ही स्मृति को इंगित करता है?

+0

वर्चुअल मेमोरी का पूरा बिंदु इस सामान को दूर करना है और कर्नेल को स्मृति प्लेसमेंट से निपटने देना है। –

+0

क्या आपके एप्लिकेशन को वर्चुअल मेमोरी के पेज जारी करने की आवश्यकता है; क्या आप आभासी पता स्थान से बाहर हो रहे हैं? –

+1

@DanielTrebbien: स्थिति निम्नानुसार है .. मुझे एक नया क्षेत्र चाहिए, इसलिए मैं इसे वर्चुअलअलोक के साथ आवंटित करने का प्रयास करता हूं। हालांकि, वर्चुअलअलोक एक आउट-ऑफ-मेमोरी फेंकता है। उसी समय, कुछ मेटाडाटा के कारण मैं खुद को रख रहा हूं, मुझे पता है कि कुछ क्षेत्र केवल आधा भरा है। अब मैं उन क्षेत्रों को सस्ता रूप से घटाना या फिर से शुरू करना चाहता हूं जब तक कि मुझे स्मृति न हो। – cib

उत्तर

3

आपने उल्लेख किया है, यह आंशिक रूप से आरक्षित पृष्ठों की एक श्रृंखला जारी करने के लिए संभव हो सकता है प्रकट नहीं होता है क्योंकि VirtualFree() documentation कहता है:

तो dwFreeType पैरामीटर MEM_RELEASE है, [lpAddress] चाहिए पेजों का क्षेत्र आरक्षित था जब VirtualAlloc समारोह द्वारा लौटा आधार पता हो।

के साथ-साथ:

dwFreeType पैरामीटर MEM_RELEASE है, तो [dwSize] होना चाहिए 0 (शून्य)।

VirtualFree() स्वयं कर्नेल फ़ंक्शन NtFreeVirtualMemory() का पतला आवरण है। Its documentation page (ZwFreeVirtualMemory() के समान) इस शब्द भी है।

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

#define NOMINMAX 
#include <windows.h> 
#include <assert.h> 
#include <stddef.h> 
#include <stdint.h> 
#include <stdio.h> 
#include <stdlib.h> 

#define RESERVATION_SIZE (256*1024) 

typedef struct st_first_reservation { 
    size_t reservation_size; 
    uint32_t rfield; 
    char premaining[0]; 
} st_first_reservation; 

int main() 
{ 
    SYSTEM_INFO sys_info = { 0 }; 
    GetSystemInfo(&sys_info); 

    assert((RESERVATION_SIZE % sys_info.dwPageSize) == 0); 

    void *vp = VirtualAlloc(NULL, 32*RESERVATION_SIZE, MEM_RESERVE, PAGE_NOACCESS); 
    if (VirtualFree(vp, 0, MEM_RELEASE) == 0) { 
     fprintf(stderr, "Error: VirtualFree() failed.\n"); 
     return EXIT_FAILURE; 
    } 

    st_first_reservation *pfirst_reservation = (st_first_reservation *) VirtualAlloc(vp, RESERVATION_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
    if (pfirst_reservation == NULL) { 
     pfirst_reservation = (st_first_reservation *) VirtualAlloc(NULL, RESERVATION_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 
     if (pfirst_reservation == NULL) { 
      fprintf(stderr, "Error: VirtualAlloc() failed.\n"); 
      return EXIT_FAILURE; 
     } 
    } 

    fprintf(stderr, "pfirst_reservation = 0x%p\n", (void *) pfirst_reservation); 

    pfirst_reservation->reservation_size = RESERVATION_SIZE; 
    pfirst_reservation->rfield = 1LU; 

    char *p = (char *) pfirst_reservation; 
    unsigned i = 1; 
    for (; i < 32; ++i) { 
     vp = VirtualAlloc(p += RESERVATION_SIZE, RESERVATION_SIZE, MEM_RESERVE, PAGE_NOACCESS); 
     if (vp != NULL) { 
      assert(((void *) vp) == p); 
      pfirst_reservation->rfield |= 1LU << i; 
      fprintf(stderr, "Obtained reservation #%u\n", i + 1); 
     } else { 
      fprintf(stderr, "Failed to obtain reservation #%u\n", i + 1); 
     } 
    } 

    fprintf(stderr, "pfirst_reservation->rfield = 0x%08x\n", pfirst_reservation->rfield); 

    return EXIT_SUCCESS; 
} 

नमूना उत्पादन: पहले 256 किबा आरक्षण एक 32-बिट अहस्ताक्षरित सा क्षेत्र है, जहां मैंवें बिट अगर मैंवें 256 किबा आरक्षण प्राप्त हुई थी सेट किया गया है शामिल हैं:

 
pfirst_reservation = 0x009A0000 
Obtained reservation #2 
Obtained reservation #3 
Obtained reservation #4 
Obtained reservation #5 
Obtained reservation #6 
Obtained reservation #7 
Obtained reservation #8 
Obtained reservation #9 
Obtained reservation #10 
Obtained reservation #11 
Obtained reservation #12 
Obtained reservation #13 
Obtained reservation #14 
Obtained reservation #15 
Obtained reservation #16 
Obtained reservation #17 
Obtained reservation #18 
Obtained reservation #19 
Obtained reservation #20 
Obtained reservation #21 
Obtained reservation #22 
Obtained reservation #23 
Obtained reservation #24 
Obtained reservation #25 
Obtained reservation #26 
Obtained reservation #27 
Obtained reservation #28 
Obtained reservation #29 
Obtained reservation #30 
Obtained reservation #31 
Obtained reservation #32 
pfirst_reservation->rfield = 0xffffffff 

संपादित करें: मैं ने पाया है कि यह बेहतर है "पूर्व आरक्षित" बत्तीस 256 किबा सभी को एक बार पर्वतमाला, नि: शुल्क है, और वें के लिए जितना आप कर सकते हैं उतना पुनः आरक्षित करने की कोशिश करें।

मैंने ऊपर कोड और नमूना आउटपुट अपडेट किया।

एक बहुप्रचारित वातावरण में, कोड पहले आरक्षण के "स्थान कहीं भी" आवंटन में वापस आ सकता है। शायद RESERVATION_SIZE बाइट्स को 32*RESERVATION_SIZE बाइट्स की आरक्षित-मुक्त-मुक्त सीमा पर पांच या उससे अधिक बार आरक्षित करने का प्रयास करना एक अच्छा विचार है, अंततः "कहीं भी स्थान" आवंटन पर वापस आना।

+0

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

+0

@cib: मुझे यकीन नहीं है कि आप बिटमैप के बिना प्राप्त कर सकते हैं या नहीं। ऐसा हो सकता है, उदाहरण के लिए, 32 वें आरक्षण प्राप्त नहीं किया जा सका। यहां तक ​​कि यदि आप सभी कॉलों को 'वर्चुअलअलोक()' को म्यूटेक्स के साथ सुरक्षित रखते हैं, तो यह भी संभव है कि किसी अन्य प्रक्रिया के लिए आपकी प्रक्रिया 'पता स्थान में वर्चुअल एडलएक्स() '] (http://msdn.microsoft' के माध्यम से वर्चुअल एड्रेस स्पेस आवंटित करना संभव हो। com/en-us/पुस्तकालय/aa366890.aspx)। –

+0

मुझे लगता है कि एक बार जब मैं स्मृति का एक संगत हिस्सा प्रदान करने में असमर्थ हूं, तो मुझे या तो एक त्रुटि को पुन: आवंटित करना या बढ़ा देना होगा। यदि मेरे "क्षेत्र" में छेद है, तो मैं इसे स्मृति के एक हिस्से के रूप में उपयोग नहीं कर सकता, बल्कि इसे अलग-अलग पृष्ठों का संग्रह, इसके रूप में इसका इलाज करना होगा। साथ ही, यह थोड़ा सा विषय है, लेकिन क्या आप समझा सकते हैं कि अन्य प्रक्रियाएं मेरी प्रक्रिया में स्मृति आवंटित क्यों कर सकती हैं? ऐसा कुछ ऐसा लगता है जो उचित इंटर-प्रोसेस अनुमति प्रणाली के बिना वैसे भी सुरक्षित नहीं होगा। – cib

2

नहीं एक जवाब है, लेकिन मैं पूछना:

दर्द आप में हैं को देखते हुए, VirtualAlloc(), और अपने कोड के गैर पोर्टेबिलिटी का प्रदर्शन हिट; जैसा कि किसी भी मूल्य VIrtualAlloc() देता है, क्या आप शायद malloc() और दोस्तों का उपयोग करने पर विचार कर सकते हैं? IOW, वर्चुअलअलोक() किसी भी वास्तविक लाभ प्रदान करता है?

मेरी राय में (शायद केवल मेरी राय), malloc() की शक्ति और सामान्यता वर्चुअलअलोक() वादे के किसी भी आकर्षण से अधिक है। और यह आपको अपने क्षेत्रों से अधिक सरलता से निपटने देगा।

गैर-उत्तर के लिए खेद है। मुझे इससे नफरत है जब लोग पूछते हैं "जो कभी भी लगता होगाकि करना है?" लेकिन निश्चित रूप से यह सब अलग है जब मैं एक हूँ "क्यों" :-)

+0

सरल, मैं अपना खुद का मॉलोक-स्तरीय मेमोरी मैनेजर लिख रहा हूं _because malloc मैं जो कर रहा हूं उसके लिए कुशल नहीं है_ – cib

+0

@cib, ज्यादातर मामलों में, भले ही मॉलोक का प्रत्यक्ष उपयोग अक्षम है, मॉलोक का अप्रत्यक्ष उपयोग (यानी, malloc एक बड़ा ब्लॉक प्राप्त करने के लिए जो आप आगे विभाजित करते हैं) आमतौर पर ठीक है ... – bdonlan

+0

@bdonlan: यह मामला हो सकता है, लेकिन यह सबसे अच्छा हैक की तरह लगता है। मॉलोक का उपयोग करके, आप कहां और कैसे आवंटित करते हैं पर आपका बहुत कम नियंत्रण है। उदाहरण के लिए, मेरी कुछ आवश्यकताओं में शायद पृष्ठ-संरेखण और पते को एक निश्चित पता-श्रेणी में शामिल किया जाएगा। निश्चित रूप से, कुछ मॉलोक कार्यान्वयन काम कर सकते हैं, लेकिन चूंकि मॉलोक सार है, आप कभी भी सुनिश्चित नहीं हो सकते हैं। – cib

1

आप आवंटन हटना चाहते हैं, आप VirtualFreeMEM_DECOMMIT साथ आवंटन की एक subrange पर उपयोग कर सकते हैं पूछ है। ध्यान दें कि यह पता स्थान को मुक्त नहीं करेगा; केवल भौतिक राम। यदि आप इसे विकसित करना चाहते हैं, तो आप अपने वर्तमान आवंटन के तुरंत बाद VirtualAlloc पते को पारित करने का प्रयास कर सकते हैं। यह निश्चित रूप से असफल हो सकता है, जिस बिंदु पर आपको स्मृति की प्रतिलिपि बनाना होगा।

आप GMEM_MOVEABLE और GlobalReAlloc (या समकक्ष हेप * फ़ंक्शन) के साथ भी उपयोग करने का प्रयास कर सकते हैं।

यदि आपको पता स्थान मुक्त करने की आवश्यकता है, तो आप अज्ञात मेमोरी-मैपिंग ऑब्जेक्ट्स का उपयोग करने और रन-टाइम पर अपनी मैप की गई विंडो को बदलने का प्रयास करना चाहेंगे - या अतिरिक्त पता स्थान प्राप्त करने के लिए बस 64-बिट का उपयोग करें।

+0

मदद नहीं करता है, वह पता स्थान से बाहर है।वर्चुअलअलोक/फ्री के पास मांग-पजे हुए वर्चुअल मेमोरी ऑपरेटिंग सिस्टम पर रैम के साथ कुछ लेना देना नहीं है। –

+0

@ हंसपैसेंट, मेरा आखिरी सुझाव देखें - वह अज्ञात मेमोरी-मैपिंग ऑब्जेक्ट्स का उपयोग कर सकता है, और उनमें से विंडोज़ मैप कर सकता है। या बस 64-बिट पर जाएं। – bdonlan

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