साझा पुस्तकालयों और रैम उपयोग का लोड हो रहा है


40

मैं जिस तरह से लिनक्स साझा पुस्तकालयों का प्रबंधन करता हूं, उसके बारे में सोच रहा हूं। (वास्तव में मैं Maemo Fremantle के बारे में बात कर रहा हूं, 2009 में 256MB RAM पर चलने वाला डेबियन आधारित डिस्ट्रो)।

मान लेते हैं कि हमारे पास libQtCore.so.4 से लिंक करने वाले दो निष्पादक हैं और इसके प्रतीकों (इसकी कक्षाओं और कार्यों का उपयोग करके) का उपयोग कर रहे हैं। सादगी के लिए चलो उन्हें कॉल करें aऔर b। हम मानते हैं कि दोनों निष्पादनयोग्य एक ही पुस्तकालयों से जुड़ते हैं।

पहले हम लॉन्च करते हैं a। पुस्तकालय को लोड करना पड़ता है। क्या यह पूरी तरह से लोड है या क्या यह केवल उस हिस्से में मेमोरी में लोड किया गया है जो आवश्यक है (जैसा कि हम प्रत्येक वर्ग का उपयोग नहीं करते हैं, केवल इस्तेमाल की गई कक्षाओं के बारे में कोड लोड किया जा रहा है)?

फिर हम लॉन्च करते हैं b। हम मानते हैं कि aअभी भी चल रहा है। blibQtCore.so.4 के लिंक भी और उपयोग करने वाले कुछ वर्गों का aउपयोग करता है, लेकिन कुछ ऐसे भी हैं जिनका उपयोग नहीं किया जाता है a। क्या पुस्तकालय डबल लोडेड (अलग-अलग aऔर अलग-अलग b) के लिए होगा? या वे उसी ऑब्जेक्ट का उपयोग रैम में पहले से ही करेंगे। यदि bकोई नया प्रतीक उपयोग नहीं करता है और aपहले से चल रहा है तो साझा पुस्तकालयों द्वारा उपयोग की जाने वाली रैम में वृद्धि होगी? (या अंतर नगण्य होगा)

जवाबों:


53

नोट: मैं मान सकता हूं कि आपकी मशीन में मेमोरी मैपिंग यूनिट (MMU) है। एक Linux संस्करण (isClinux) है जिसे MMU की आवश्यकता नहीं है, और यह उत्तर वहां लागू नहीं होता है।

MMU क्या है? यह प्रोसेसर और / या मेमोरी कंट्रोलर का हार्डवेयर- पार्ट है। साझा लाइब्रेरी को समझना आपको यह समझने की आवश्यकता नहीं है कि एमएमयू कैसे काम करता है, बस यह कि एमएमयू तार्किक मेमोरी एड्रेस (कार्यक्रमों द्वारा उपयोग किए जाने वाले) और भौतिक के बीच अंतर करने की अनुमति देता हैमेमोरी एड्रेस (वास्तव में मेमोरी बस में मौजूद हैं)। मेमोरी को पृष्ठों में तोड़ दिया जाता है, आमतौर पर लिनक्स पर आकार में 4K। 4k पृष्ठों के साथ, तार्किक पते 0–4095 पृष्ठ 0 हैं, तार्किक पते 4096–8191 पृष्ठ 1 हैं, आदि। MMU उन RAM के भौतिक पृष्ठों को मैप करते हैं, और प्रत्येक तार्किक पृष्ठ को आमतौर पर 0 या 1 भौतिक पृष्ठों पर मैप किया जा सकता है। एक दिया गया भौतिक पृष्ठ कई तार्किक पृष्ठों के अनुरूप हो सकता है (यह है कि मेमोरी कैसे साझा की जाती है: कई तार्किक पृष्ठ एक ही भौतिक पृष्ठ के अनुरूप हैं)। ध्यान दें कि यह ओएस की परवाह किए बिना लागू होता है; यह हार्डवेयर का विवरण है।

प्रक्रिया स्विच पर, कर्नेल MMU पृष्ठ मैपिंग को बदलता है, ताकि प्रत्येक प्रक्रिया का अपना स्थान हो। पता 4096 प्रक्रिया में 1000 हो सकता है (और आमतौर पर) प्रक्रिया 1001 में पते 4096 से पूरी तरह से अलग है।

जब भी आप किसी पते को देखते हैं, तो यह एक तार्किक पता है। उपयोगकर्ता अंतरिक्ष कार्यक्रम शायद ही कभी शारीरिक पतों से निपटते हैं।

अब, पुस्तकालयों के निर्माण के भी कई तरीके हैं। मान लीजिए कि कोई प्रोग्राम foo()लाइब्रेरी में फ़ंक्शन को कॉल करता है। सीपीयू प्रतीकों के बारे में कुछ भी नहीं जानता है, या फ़ंक्शन कॉल वास्तव में करता है - यह सिर्फ एक तार्किक पते पर कूदना जानता है, और जो भी कोड वहां मिलता है उसे निष्पादित करता है। कुछ तरीके हैं जो यह कर सकते हैं (और इसी तरह की चीजें तब लागू होती हैं जब एक पुस्तकालय अपने स्वयं के वैश्विक डेटा तक पहुंचता है, आदि):

  1. इसे कॉल करने के लिए कुछ लॉजिकल एड्रेस को हार्ड-कोड कर सकते हैं। इसके लिए आवश्यक है कि लाइब्रेरी को हमेशा उसी तार्किक पते पर लोड किया जाए। यदि दो पुस्तकालयों को समान पते की आवश्यकता होती है, तो डायनेमिक लिंकिंग विफल हो जाती है और आप प्रोग्राम लॉन्च नहीं कर सकते। पुस्तकालयों को अन्य पुस्तकालयों की आवश्यकता हो सकती है, इसलिए मूल रूप से इस प्रणाली के प्रत्येक पुस्तकालय के लिए अद्वितीय तार्किक पते होने चाहिए। यह बहुत तेज़ है, हालांकि, अगर यह काम करता है। (यह है कि कैसे चीजों के बारे में किया गया था, और उस तरह का सेट जो प्रीलिंकिंग करता है, सॉर्ट करता है)।
  2. यह एक नकली तार्किक पते को हार्ड-कोड कर सकता है, और लाइब्रेरी को लोड करते समय डायनेमिक लिंकर को उचित एक में संपादित करने के लिए कह सकता है। यह पुस्तकालयों को लोड करते समय बहुत कम समय खर्च करता है, लेकिन इसके बाद यह बहुत तेज होता है।
  3. यह अप्रत्यक्ष की एक परत जोड़ सकता है: लाइब्रेरी को लोड किए जाने वाले तार्किक पते को होल्ड करने के लिए सीपीयू रजिस्टर का उपयोग करें , और फिर उस रजिस्टर से ऑफसेट के रूप में सब कुछ एक्सेस करें। यह प्रत्येक एक्सेस पर एक प्रदर्शन लागत लगाता है।

बहुत ज्यादा कोई भी # 1 का उपयोग नहीं करता है, कम से कम सामान्य-उद्देश्य प्रणालियों पर नहीं। उस अद्वितीय तार्किक पता सूची को रखना 32-बिट सिस्टम (चारों ओर जाने के लिए पर्याप्त नहीं है) और 64-बिट सिस्टम पर एक प्रशासनिक दुःस्वप्न पर असंभव है। प्री-लिंकिंग सॉर्ट ऐसा करता है, हालांकि, प्रति-प्रणाली के आधार पर।

क्या # 2 या # 3 का उपयोग किया जाता है यह निर्भर करता है कि लाइब्रेरी को GCC -fPIC(स्थिति स्वतंत्र कोड) विकल्प के साथ बनाया गया था या नहीं । # 2 बिना है, # 3 साथ है। आमतौर पर, पुस्तकालयों के साथ बनाया जाता है -fPIC, इसलिए # 3 क्या होता है।

अधिक जानकारी के लिए, Ulrich Drepper की हाउ टू राइट टू शेयर्ड लाइब्रेरीज़ (PDF) देखें

तो, अंत में, आपके प्रश्न का उत्तर दिया जा सकता है:

  1. यदि पुस्तकालय के साथ बनाया गया है-fPIC (जैसा कि यह लगभग निश्चित रूप से होना चाहिए), पृष्ठों का विशाल बहुमत हर प्रक्रिया के लिए बिल्कुल समान है जो इसे लोड करता है। आपकी प्रक्रियाएँ aऔर bपुस्तकालय विभिन्न तार्किक पतों पर अच्छी तरह लोड हो सकते हैं, लेकिन वे एक ही भौतिक पृष्ठों की ओर संकेत करेंगे: स्मृति साझा की जाएगी। इसके अलावा, रैम में डेटा डिस्क पर क्या होता है, इसके साथ मेल खाता है, इसलिए इसे केवल पृष्ठ दोष हैंडलर द्वारा आवश्यक होने पर लोड किया जा सकता है।
  2. यदि पुस्तकालय के बिना बनाया गया है-fPIC , तो यह पता चला है कि पुस्तकालय के अधिकांश पृष्ठों को लिंक संपादन की आवश्यकता होगी, और अलग होगा। इसलिए, उन्हें अलग-अलग भौतिक पृष्ठ होने चाहिए (क्योंकि उनमें अलग-अलग डेटा होते हैं)। इसका मतलब है कि वे साझा नहीं हैं। पृष्ठों का मिलान डिस्क पर नहीं होता है, इसलिए मुझे आश्चर्य नहीं होगा यदि पूरी लाइब्रेरी लोड हो गई है। यह निश्चित रूप से बाद में डिस्क (स्वैप में) तक स्वैप किया जा सकता है।

आप pmapटूल के साथ या सीधे विभिन्न फ़ाइलों की जाँच करके इसकी जांच कर सकते हैं /proc। उदाहरण के लिए, यहां pmap -xदो अलग-अलग नव-स्पंदित bcएस पर (आंशिक) आउटपुट है । ध्यान दें कि pmap द्वारा दिखाए गए पते विशिष्ट, तार्किक पते के रूप में हैं:

pmap -x 14739
Address           Kbytes     RSS   Dirty Mode  Mapping
00007f81803ac000     244     176       0 r-x-- libreadline.so.6.2
00007f81803e9000    2048       0       0 ----- libreadline.so.6.2
00007f81805e9000       8       8       8 r---- libreadline.so.6.2
00007f81805eb000      24      24      24 rw--- libreadline.so.6.2


pmap -x 17739
Address           Kbytes     RSS   Dirty Mode  Mapping
00007f784dc77000     244     176       0 r-x-- libreadline.so.6.2
00007f784dcb4000    2048       0       0 ----- libreadline.so.6.2
00007f784deb4000       8       8       8 r---- libreadline.so.6.2
00007f784deb6000      24      24      24 rw--- libreadline.so.6.2

आप देख सकते हैं कि पुस्तकालय कई हिस्सों में भरा हुआ है, और pmap -xआपको प्रत्येक पर अलग से विवरण देता है। आप देखेंगे कि दो प्रक्रियाओं के बीच तार्किक पते अलग-अलग हैं; आप यथोचित उम्मीद करते हैं कि वे एक ही हो (चूंकि एक ही कार्यक्रम चल रहा है, और कंप्यूटर आमतौर पर उसी तरह अनुमानित हैं), लेकिन एक सुरक्षा सुविधा है जिसे एड्रेस स्पेस लेआउट रैंडमाइजेशन कहा जाता है जो जानबूझकर उन्हें यादृच्छिक बनाता है।

आप आकार (Kbytes) और निवासी आकार (RSS) के अंतर से देख सकते हैं कि पूरे पुस्तकालय खंड को लोड नहीं किया गया है। अंत में, आप देख सकते हैं कि बड़े मैपिंग के लिए, गंदा 0 है, जिसका अर्थ है कि यह डिस्क पर वास्तव में मेल खाता है।

आप के साथ फिर से चला सकते हैं pmap -XX, और यह आपको दिखाएगा- आप जिस कर्नेल संस्करण पर चल रहे हैं, उसके आधार पर -XX आउटपुट कर्नेल संस्करण से भिन्न होता है - जिसमें पहली मैपिंग में Shared_Clean176 होती है, जो वास्तव में मेल खाती है RSSSharedमेमोरी का मतलब है कि भौतिक पेज कई प्रक्रियाओं के बीच साझा किए जाते हैं, और चूंकि यह आरएसएस से मेल खाता है, इसका मतलब है कि सभी पुस्तकालय जो स्मृति में हैं, साझा किए गए हैं (साझा बनाम निजी के आगे स्पष्टीकरण के लिए नीचे देखें):

pmap -XX 17739
         Address Perm   Offset Device   Inode  Size  Rss Pss Shared_Clean Shared_Dirty Private_Clean Private_Dirty Referenced Anonymous AnonHugePages Swap KernelPageSize MMUPageSize Locked                   VmFlagsMapping
    7f784dc77000 r-xp 00000000  fd:00 1837043   244  176  19          176            0             0             0        176         0             0    0              4           4      0       rd ex mr mw me sd  libreadline.so.6.2
    7f784dcb4000 ---p 0003d000  fd:00 1837043  2048    0   0            0            0             0             0          0         0             0    0              4           4      0             mr mw me sd  libreadline.so.6.2
    7f784deb4000 r--p 0003d000  fd:00 1837043     8    8   8            0            0             0             8          8         8             0    0              4           4      0       rd mr mw me ac sd  libreadline.so.6.2
    7f784deb6000 rw-p 0003f000  fd:00 1837043    24   24  24            0            0             0            24         24        24             0    0              4           4      0    rd wr mr mw me ac sd  libreadline.so.6.2


यह भी देखें


इसका मतलब है कि प्रीलिंकिंग का कोई फायदा नहीं है (और यह -fPICउपयोग कुछ समय पहले पूरी तरह बदल गया है)?
हौके लैजिंग

@ क्रिसन सुधार के लिए धन्यवाद। FYI करें, मार्कडाउन आपके लिए गिना जाएगा- मेरे बार-बार प्रस्तुत किए गए आउटपुट 1. सही थे। इसके अलावा, मैंने आपके द्वारा किए गए कुछ बदलाव किए- "स्टार्ट एड्रेस" तकनीकी शब्दजाल है, मुझे संभवतः बीच में "तार्किक" लगाकर भ्रम पैदा किया। मैंने इसे शब्दजाल से छुटकारा पाने के लिए बदल दिया। इसके अलावा, पृष्ठ उन पतों के बराबर हैं, AFAIK उन पतों के लिए कभी भी एक अलग पृष्ठ होना संभव नहीं है। मैंने फिर से कोशिश की, आदेश को स्वैप कर रहा था, उम्मीद है कि यह स्पष्ट हो।
फोबर्ट

अरे, अब यह एक जवाब है !!!
इवान कैरोल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.