2010-08-13 17 views
92

क्या कोई बता सकता है कि malloc() आंतरिक रूप से कैसे काम करता है?malloc() को आंतरिक रूप से कैसे कार्यान्वित किया जाता है?

मैं कभी कभी strace program किया है और मैं sbrk सिस्टम कॉल का एक बहुत देखते हैं, malloc() में इस्तेमाल किया जा रहा है इसके बारे में बात करती है man sbrk लेकिन बहुत ज्यादा नहीं कर रही।

+2

स्रोत, बोडा साइडो का उपयोग करें। http://ftp.gnu.org/gnu/glibc/ – msw

+0

मैं इस लिंक को कुछ हद तक आपके प्रश्न के उत्तर लगता है http://stackoverflow.com/questions/1119134/how-malloc-and-free-work – Rishabh

उत्तर

87

sbrk सिस्टम कॉल डेटा सेगमेंट की "सीमा" को स्थानांतरित करता है। इसका अर्थ यह है कि यह उस क्षेत्र की सीमा को स्थानांतरित करता है जिसमें एक प्रोग्राम डेटा को पढ़/लिख सकता है (इसे बढ़ने या घटाने देना, हालांकि AFAIK no malloc वास्तव में उस विधि के साथ कर्नेल को मेमोरी सेगमेंट देता है)। इसके अलावा, mmap भी है जो फ़ाइलों को स्मृति में मैप करने के लिए उपयोग किया जाता है लेकिन स्मृति को आवंटित करने के लिए भी उपयोग किया जाता है (यदि आपको साझा मेमोरी आवंटित करने की आवश्यकता है, तो mmap यह है कि आप इसे कैसे करते हैं)।

तो आपके पास कर्नेल से अधिक मेमोरी प्राप्त करने के दो तरीके हैं: sbrk और mmap। कर्नेल से मिली मेमोरी को व्यवस्थित करने के तरीके पर विभिन्न रणनीतियां हैं।

एक बेवकूफ तरीका इसे ज़ोन में विभाजित करना है, जिसे अक्सर "बाल्टी" कहा जाता है, जो कुछ संरचना आकारों के लिए समर्पित होते हैं। उदाहरण के लिए, malloc कार्यान्वयन 16, 64, 256 और 1024 बाइट संरचनाओं के लिए बाल्टी बना सकता है। यदि आप किसी दिए गए आकार की स्मृति देने के लिए malloc पूछते हैं तो यह उस नंबर को अगले बाल्टी आकार तक ले जाता है और फिर आपको उस बाल्टी से एक तत्व देता है। यदि आपको कर्नेल के साथ आवंटित करने के लिए mmap का उपयोग करने के लिए एक बड़े क्षेत्र की आवश्यकता है। यदि एक निश्चित आकार की बाल्टी खाली है malloc नई बाल्टी के लिए अधिक जगह पाने के लिए sbrk का उपयोग कर सकती है।

विभिन्न malloc डिज़ाइन हैं और malloc को लागू करने का कोई भी सही तरीका नहीं है क्योंकि आपको गति, ओवरहेड और विखंडन/अंतरिक्ष प्रभावशीलता से परहेज करने की आवश्यकता है। उदाहरण के लिए, यदि बाल्टी तत्वों से बाहर निकलती है तो कार्यान्वयन को एक बड़ी बाल्टी से तत्व मिल सकता है, इसे विभाजित कर दें और इसे तत्वों से बाहर निकलने वाली बाल्टी में जोड़ें। यह काफी जगह कुशल होगा लेकिन हर डिजाइन के साथ संभव नहीं होगा। यदि आपको sbrk/mmap के माध्यम से बस एक और बाल्टी मिलती है जो कि तेज और आसान हो सकती है, लेकिन अंतरिक्ष कुशल नहीं है। साथ ही, डिज़ाइन को निश्चित रूप से ध्यान में रखना चाहिए कि "मुक्त" को किसी भी तरह malloc पर स्थान उपलब्ध कराने की आवश्यकता है। आप इसका पुन: उपयोग किए बिना स्मृति को हाथ से नहीं निकालते हैं।

यदि आप रुचि रखते हैं, तो OpenSER/Kamailio SIP प्रॉक्सी में दो malloc कार्यान्वयन हैं (उन्हें स्वयं की आवश्यकता है क्योंकि वे साझा स्मृति का भारी उपयोग करते हैं और सिस्टम malloc साझा स्मृति का समर्थन नहीं करता है)। देखें: https://github.com/OpenSIPS/opensips/tree/master/mem

फिर आप GNU libc malloc implementation पर भी देख सकते हैं, लेकिन यह बहुत जटिल है, आईआईआरसी।

+2

IIRC = अगर मैं सही ढंग से याद करता हूं –

37

Simplistically malloc और इस तरह मुक्त काम:

malloc एक प्रक्रिया के ढेर तक पहुँच प्रदान करता। ढेर सी कोर लाइब्रेरी (आमतौर पर libc) में एक निर्माण है जो वस्तुओं को प्रक्रिया के ढेर पर कुछ जगह तक विशेष पहुंच प्राप्त करने की अनुमति देता है।

ढेर पर प्रत्येक आवंटन को एक हीप सेल कहा जाता है। इसमें आम तौर पर एक शीर्षलेख होता है जिसमें सेल के आकार के साथ-साथ अगले हीप सेल में पॉइंटर भी होता है। यह एक ढेर प्रभावी ढंग से एक लिंक्ड सूची बनाता है।

जब कोई प्रक्रिया शुरू करता है, तो ढेर में एक एकल कक्ष होता है जिसमें स्टार्टअप पर आवंटित सभी ढेर स्थान होते हैं। यह सेल ढेर की मुफ्त सूची पर मौजूद है।

जब कोई मॉलोक को कॉल करता है, तो बड़े हेप सेल से स्मृति ली जाती है, जिसे मॉलोक द्वारा वापस किया जाता है। बाकी को एक नए हीप सेल में बनाया गया है जिसमें शेष स्मृति शामिल है।

जब कोई स्मृति को मुक्त करता है, तो हीप सेल ढेर की मुफ्त सूची के अंत में जोड़ा जाता है। बाद के मॉलॉक्स उपयुक्त आकार के एक सेल की तलाश में मुफ्त सूची चलते हैं।

जैसा कि उम्मीद की जा सकती है कि ढेर खंडित हो सकता है और ढेर प्रबंधक समय-समय पर हो सकता है, आसन्न ढेर कोशिकाओं को विलय करने का प्रयास करें।

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

अब ढेर परिचालन को अनुकूलित करने के लिए कुछ संशोधन हैं।

  • बड़े स्मृति आवंटन (आमतौर> 512 बाइट्स के लिए, ढेर प्रबंधक ओएस के लिए सीधे जा सकते हैं और एक पूर्ण स्मृति पेज का आवंटन।
  • ढेर को आवंटन की एक न्यूनतम आकार निर्दिष्ट कर सकता है बड़ी मात्रा में विखंडन की को रोकने के।
  • ढेर भी अपने डिब्बे में बड़ा आवंटन के लिए छोटे आवंटन के लिए और एक बड़ा आवंटन तेज बनाने के लिए विभाजित कर सकते हैं।
  • अल रहे हैं बहु थ्रेडेड ढेर आवंटन को अनुकूलित करने के लिए इतनी चतुर तंत्र।
7

यह भी एहसास है कि बस brk और sbrk के साथ चारों ओर कार्यक्रम को तोड़ने सूचक चलती स्मृति को आबंटित वास्तव में नहीं है महत्वपूर्ण है, यह सिर्फ पता स्थान सेट करता है। लिनक्स पर, उदाहरण के लिए, स्मृति को वास्तविक भौतिक पृष्ठों द्वारा "समर्थित" किया जाएगा, जब उस पते की सीमा का उपयोग किया जाएगा, जिसके परिणामस्वरूप पृष्ठ गलती होगी, और अंत में कर्नेल को पृष्ठ आवंटक में बैकिंग पृष्ठ प्राप्त करने के लिए बुलाया जाएगा।