2009-05-26 9 views
58

लिनक्स पर अगर मैं malloc(1024 * 1024 * 1024) पर था, तो वास्तव में मॉलोक क्या करता है?क्या मैलोक लिनक्स (और अन्य प्लेटफॉर्म) पर आवंटन के लिए आलसी पृष्ठों का आलसी बनाता है?

मुझे यकीन है कि यह आवंटन के लिए एक आभासी पता असाइन करता है (मुफ्त सूची चलकर और यदि आवश्यक हो तो एक नया मैपिंग बनाकर), लेकिन क्या यह वास्तव में 1 जीबीबी स्वैप पृष्ठों के लायक बनाता है? या यह mprotect पता श्रेणी है और जब आप वास्तव में उन्हें mmap करते हैं तो पृष्ठों को बनाते हैं?

(मैं लिनक्स को निर्दिष्ट कर रहा हूँ क्योंकि the standard विवरण के इन प्रकार पर खामोश है, लेकिन मैं पता है कि अन्य प्लेटफार्मों के रूप में अच्छी तरह से करने के इच्छुक होगी।)

+1

दिलचस्प सवाल; मैं अन्य प्लेटफॉर्म पर भी व्यवहार के बारे में उत्सुक हूं, लेकिन इस सवाल को लिनक्स पर लॉक करने के लिए कुडोस। –

उत्तर

35

लिनक्स स्थगित पृष्ठ आवंटन, उर्फ ​​करता है। 'आशावादी स्मृति आवंटन'। मॉलोक से वापस आने वाली मेमोरी को किसी भी चीज़ का समर्थन नहीं किया जाता है और जब आप इसे स्पर्श करते हैं तो आपको वास्तव में ओओएम स्थिति मिल सकती है (यदि आपके द्वारा अनुरोधित पृष्ठ के लिए कोई स्वैप स्थान नहीं है), तो a process is unceremoniously terminated पर।

उदाहरण http://www.linuxdevcenter.com/pub/a/linux/2006/11/30/linux-out-of-memory.html

+3

यह देखना दिलचस्प है कि कर्नेल एक प्रक्रिया के "बुरेपन" की गणना कैसे करता है यह पता लगाने के लिए कि कौन सी प्रक्रिया (एस) स्मृति से बाहर होने पर मारने के लिए। – JesperE

+0

आईआईआरसी में इसके स्तर हैं: उच्चतम से निम्नतम - रूट प्रक्रियाएं, I/O प्रदर्शन करने वाली प्रक्रियाएं, प्रक्रियाओं को सोना ...सबसे कम बुलेट प्राप्त करें। –

+0

@Aiden "बुराई" फ़ंक्शन जिसका उपयोग यह निर्धारित करने के लिए किया जाता है कि लिंक में कौन सी प्रक्रिया को मारने के लिए लिंक किया गया है। –

13

9. Memory (Andries ब्रौवेर द्वारा The Linux kernel, Some remarks on the Linux Kernel का हिस्सा) एक अच्छा दस्तावेज़ है।

इसमें निम्न प्रोग्राम शामिल हैं जो वास्तविक स्मृति बनाम लिनक्स के भौतिक स्मृति के संचालन को प्रदर्शित करते हैं और कर्नेल के आंतरिक बताते हैं।

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

डेमो प्रोग्राम 1: इसका उपयोग किए बिना स्मृति आवंटित करें।

#include <stdio.h> 
#include <stdlib.h> 

int main (void) { 
    int n = 0; 

    while (1) { 
     if (malloc(1<<20) == NULL) { 
       printf("malloc failure after %d MiB\n", n); 
       return 0; 
     } 
     printf ("got %d MiB\n", ++n); 
    } 
} 

डेमो कार्यक्रम 2: स्मृति को आबंटित है और वास्तव में यह सब स्पर्श करें।

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main (void) { 
    int n = 0; 
    char *p; 

    while (1) { 
     if ((p = malloc(1<<20)) == NULL) { 
       printf("malloc failure after %d MiB\n", n); 
       return 0; 
     } 
     memset (p, 0, (1<<20)); 
     printf ("got %d MiB\n", ++n); 
    } 
} 

डेमो प्रोग्राम 3: पहले आवंटित करें और बाद में उपयोग करें।

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

#define N  10000 

int main (void) { 
    int i, n = 0; 
    char *pp[N]; 

    for (n = 0; n < N; n++) { 
     pp[n] = malloc(1<<20); 
     if (pp[n] == NULL) 
      break; 
    } 
    printf("malloc failure after %d MiB\n", n); 

    for (i = 0; i < n; i++) { 
     memset (pp[i], 0, (1<<20)); 
     printf("%d\n", i+1); 
    } 

    return 0; 
} 

(एक अच्छी तरह से कार्य प्रणाली पर, Solaris की तरह, तीन डेमो कार्यक्रमों स्मृति का एक ही राशि प्राप्त करने और दुर्घटना नहीं है, लेकिन malloc() वापसी शून्य देखें।)

+4

"अच्छी तरह से काम करना" राय का विषय है। असल में, लिनक्स में ओवरकिटिट व्यवहार को नियंत्रित करने के लिए/proc/sys/vm में विकल्प हैं। यदि आप चाहें तो हो सकता है कि आपके पास सोलारिस हो। –

+2

चेतावनी दी जानी चाहिए,/proc/sys/vm ज्यादातर समय ब्रोकन है !! http://groups.google.com/group/comp.os.linux.development.system/browse_thread/thread/81c4beda045b07ca/ec471bf222d9a346?show_docid=ec471bf222d9a346&pli=1 यहाँ लिनक्स और डिस्क निष्पादन के लिए एक अच्छा सुझाव है। यदि आप कभी भी एक बड़ी प्रतिलिपि कर रहे हैं, और बहुत सारे कैश का उपयोग हो रहा है, और आपका I/O सिस्टम शुरू हो रहा है .... echo 1>/proc/sys/vm/drop_caches फिर अपनी बैक अप को बदल दें उच्च-थ्रूपुट के लिए :) आंकड़े जाओ !! – RandomNickName42

2

सबसे यूनिक्स पर सिस्टम की तरह, यह brk सीमा का प्रबंधन करता है। प्रोसेसर द्वारा मारा जाने पर वीएम पेज जोड़ता है। कम से कम लिनक्स और BSDs ऐसा करें।

4

Windows पर के लिए देखें, पृष्ठों के लिए प्रतिबद्ध हैं (अर्थात, मुक्त स्मृति उपलब्ध नीचे चला जाता है), लेकिन वे वास्तव में जब तक आप को छूने के पन्नों (या तो पढ़ना या लिखना) आवंटित नहीं किया जाएगा।

9

मैं एक ही विषय पर एक समान पद को यह जवाब दिया:

Are some allocators lazy?

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

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

इसका उद्देश्य क्या है? यह मूल रूप से मैलोकिंग मेमोरी को बिग ओ (एन) ऑपरेशन के बजाय बिग ओ (1) की तरह कम करता है (जिस तरह से लिनक्स शेड्यूलर इसे एक बड़े हिस्से में करने के बजाए इसे बाहर कर देता है)।

प्रदर्शित करने के लिए मैं क्या मतलब है मैं निम्नलिखित प्रयोग किया:

[email protected]:~/test_code$ time ./bigmalloc 

real 0m0.005s 
user 0m0.000s 
sys 0m0.004s 
[email protected]:~/test_code$ time ./deadbeef 

real 0m0.558s 
user 0m0.000s 
sys 0m0.492s 
[email protected]:~/test_code$ time ./justwrites 

real 0m0.006s 
user 0m0.000s 
sys 0m0.008s 

bigmalloc कार्यक्रम 20 मिलियन ints आबंटित करता है, लेकिन उनके साथ कुछ भी नहीं है। डेडबीफ 1 9 51 में लिखने वाले प्रत्येक पृष्ठ के लिए एक int लिखता है और लिखता है और लिखता है 1 9 31 के इनट्स को आवंटित करता है और उन्हें शून्य करता है। जैसा कि आप देख सकते हैं कि डेडबीफ को bigmalloc से निष्पादित करने के लिए लगभग 100 गुना अधिक समय लगता है और केवल लिखने से 50 गुना लंबा होता है।

#include <stdlib.h> 

int main(int argc, char **argv) { 

    int *big = malloc(sizeof(int)*20000000); // Allocate 80 million bytes 

    return 0; 
} 

#include <stdlib.h> 

int main(int argc, char **argv) { 

    int *big = malloc(sizeof(int)*20000000); // Allocate 80 million bytes 

    // Immediately write to each page to simulate an all-at-once allocation 
    // assuming 4k page size on a 32-bit machine. 

    for (int* end = big + 20000000; big < end; big += 1024) 
     *big = 0xDEADBEEF; 

    return 0; 
} 

#include <stdlib.h> 

int main(int argc, char **argv) { 

    int *big = calloc(sizeof(int), 19531); // Number of writes 

    return 0; 
} 
4

मॉलोक libc द्वारा प्रबंधित ब्लॉक से स्मृति को आवंटित करता है। जब अतिरिक्त मेमोरी की आवश्यकता होती है तो पुस्तकालय ब्रैक सिस्टम कॉल का उपयोग कर कर्नेल में जाता है।

कर्नेल कॉलिंग प्रक्रिया में वर्चुअल मेमोरी के पृष्ठों को आवंटित करता है। पृष्ठों को प्रक्रिया के स्वामित्व वाले संसाधनों के हिस्से के रूप में प्रबंधित किया जाता है। स्मृति पृष्ठों को ब्रोक किए जाने पर भौतिक पृष्ठ आवंटित नहीं किए जाते हैं। जब प्रक्रिया ब्रैक किए गए पृष्ठों में से किसी एक मेमोरी स्थान तक पहुंच जाती है तो पेज गलती होती है। कर्नेल मान्य करता है कि वर्चुअल मेमोरी को वर्चुअल पेज पर भौतिक पृष्ठ को मैप करने के लिए आवंटित किया गया है और प्राप्त किया गया है।

पृष्ठ आवंटन सीमित तक सीमित नहीं है और लिखने पर प्रतिलिपि से काफी अलग है। किसी भी पहुंच, पढ़ने या लिखने के परिणामस्वरूप, किसी पृष्ठ पृष्ठ की गलती और भौतिक पृष्ठ का मानचित्रण होता है।

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

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