16

this question का विश्लेषण करते हुए मुझे लिनक्स पर गतिशील लोडिंग (dlopen) के संदर्भ में कमजोर प्रतीक संकल्प के व्यवहार के बारे में कुछ चीजें मिलीं। अब मैं इसे नियंत्रित करने वाले विनिर्देशों की तलाश में हूं।गतिशील लोडिंग और कमजोर प्रतीक संकल्प

चलिए an example लेते हैं। मान लीजिए कि एक प्रोग्राम a है जो उस क्रम में लाइब्रेरी b.so और c.so गतिशील रूप से लोड करता है। यदि c.so उस उदाहरण में दो अन्य पुस्तकालयों foo.so (वास्तव में libgcc.so) और bar.so (वास्तव में libpthread.so) पर निर्भर करता है, तो आमतौर पर bar.so द्वारा निर्यात किए गए प्रतीकों का उपयोग foo.so में कमजोर प्रतीक संबंधों को पूरा करने के लिए किया जा सकता है। लेकिन अगर b.sofoo.so पर भी निर्भर करता है लेकिन bar.so पर नहीं, तो इन कमजोर प्रतीकों को स्पष्ट रूप से bar.so के खिलाफ लिंक नहीं किया जाएगा। ऐसा लगता है जैसे foo.so इंकेज केवल a और b.so और उनकी सभी निर्भरताओं से प्रतीकों की तलाश करते हैं।

यह कुछ हद तक, समझ में आता है के बाद से अन्यथा c.so लोड हो रहा है कुछ बिंदु जहां b.so पहले से ही पुस्तकालय का उपयोग कर रहा है पर foo.so के व्यवहार बदल सकता है। दूसरी तरफ, जिस प्रश्न में मैंने इसे शुरू किया, उसमें काफी परेशानी हुई, इसलिए मुझे आश्चर्य है कि इस समस्या के आसपास कोई रास्ता है या नहीं। और आसपास के तरीकों को खोजने के लिए, मुझे सबसे सटीक विवरणों के बारे में अच्छी समझ की आवश्यकता है कि इन मामलों में प्रतीक समाधान कैसे निर्दिष्ट किया गया है।

विनिर्देश या अन्य तकनीकी दस्तावेज इन स्थितियों में सही व्यवहार को परिभाषित करने के क्या है?

+0

क्या आपने [इस पीडीएफ] (http://refspecs.linuxbase.org/elf/elf.pdf) पर एक नज़र डाली है? दिलचस्प डेटा के बहुत सारे, लेकिन यह सुनिश्चित नहीं है कि इसमें क्या शामिल है। – rodrigo

+0

@rodrigo: यह सुनिश्चित नहीं है कि यह ऐसा था या कुछ समान था, लेकिन अब तक सभी ईएलएफ दस्तावेज़ों को मैंने बाइनरी के निष्पादन से पहले गतिशील लिंकिंग का वर्णन किया है, न कि गतिशील रूप से लोड की गई वस्तुओं में शामिल लिंक। यह एक लंबा दस्तावेज़ है, और मैंने गलत जगहों पर देखा होगा, लेकिन अब तक ऐसा लगता है कि मैं जो खोज रहा हूं वह नहीं है। – MvG

+0

और इसके बारे में क्या [ड्रेपर पोस्ट] (http://www.sourceware.org/ml/libc-hacker/2000-06/msg00029.html) और इसके कम या कम [संबंधित दस्तावेज़] (http: // www। akkadia.org/drepper/dsohowto.pdf) (धारा 1.5.2 देखें)? जैसा कि मैंने इसकी व्याख्या की है, कमजोर प्रतीकों का उपयोग केवल स्थिर लिंकिंग के लिए किया जाता है। तो 'dlopen()' कमजोर और मजबूत प्रतीकों के बीच एक अंतर नहीं होगा। – rodrigo

उत्तर

11

दुर्भाग्य से, आधिकारिक प्रलेखन स्रोत कोड है। लिनक्स के अधिकांश वितरण glibc या इसके कांटा, eglibc का उपयोग करें। दोनों के लिए स्रोत कोड में, इस प्रकार फ़ाइल कि dlopen दस्तावेज़ चाहिए() पढ़ता है:

मैनुअल/libdl.texi

@c FIXME these are undocumented: 
@c dladdr 
@c dladdr1 
@c dlclose 
@c dlerror 
@c dlinfo 
@c dlmopen 
@c dlopen 
@c dlsym 
@c dlvsym 

है क्या तकनीकी विनिर्देश वहाँ ELF specification और POSIX मानक से तैयार किया जा सकता । ईएलएफ विनिर्देश एक कमजोर प्रतीक अर्थपूर्ण बनाता है। POSIX वास्तविक specification for dlopen() स्वयं है।

यही वह है जो मुझे ईएलएफ विनिर्देश का सबसे प्रासंगिक हिस्सा माना जाता है।

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

ईएलएफ विनिर्देश गतिशील लोडिंग का कोई संदर्भ नहीं देता है, इसलिए बाकी का अनुच्छेद मेरी अपनी व्याख्या है। उपर्युक्त प्रासंगिक मुझे ढूंढने का कारण यह है कि प्रतीकों को हल करना एक "कब" होता है। उदाहरण में आप देते हैं, जब प्रोग्राम a गतिशील रूप से b.so लोड करता है, गतिशील लोडर अपरिभाषित प्रतीकों को हल करने का प्रयास करता है। यह या तो वैश्विक या कमजोर प्रतीकों के साथ ऐसा कर सकता है। जब प्रोग्राम गतिशील रूप से c.so लोड करता है, तो गतिशील लोडर फिर से अपरिभाषित प्रतीकों को हल करने का प्रयास करता है। परिदृश्य में आप वर्णन करते हैं, b.so में प्रतीकों को कमजोर प्रतीकों के साथ हल किया गया था। एक बार हल हो जाने के बाद, उन प्रतीकों को अब अपरिभाषित नहीं किया गया है। इससे कोई फर्क नहीं पड़ता कि वैश्विक या कमजोर प्रतीकों का इस्तेमाल उन्हें परिभाषित करने के लिए किया गया था। c.so उस समय तक पहले से ही अपरिभाषित नहीं हैं।

ईएलएफ विनिर्देश किसी लिंक संपादक के बारे में कोई सटीक परिभाषा नहीं देता है या जब लिंक संपादक को ऑब्जेक्ट फ़ाइलों को जोड़ना होगा। संभवतः यह एक गैर-मुद्दा है क्योंकि दस्तावेज़ में दिमागी-गतिशीलता है।

POSIX कुछ dlopen() कार्यक्षमता का वर्णन करता है लेकिन आपके प्रश्न के पदार्थ सहित कार्यान्वयन के लिए बहुत अधिक छोड़ देता है। POSIX सामान्य रूप से ईएलएफ प्रारूप या कमजोर प्रतीकों का कोई संदर्भ नहीं देता है। Dlopen() को लागू करने वाले सिस्टम के लिए कमजोर प्रतीकों की कोई धारणा भी नहीं है।

http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html

POSIX अनुपालन एक और मानक, लिनक्स स्टैंडर्ड बेस का हिस्सा है। लिनक्स वितरण इन मानकों का पालन करना चुन सकता है या नहीं भी हो सकता है और प्रमाणित होने की परेशानी पर जा सकता है या नहीं। उदाहरण के लिए, मैं समझता हूं कि ओपन ग्रुप द्वारा औपचारिक यूनिक्स प्रमाणीकरण काफी महंगा है - इसलिए "यूनिक्स जैसी" प्रणालियों की बहुतायत।

dlopen() के मानक अनुपालन के बारे में एक दिलचस्प बिंदु Wikipedia article for dynamic loading पर बनाया गया है। डीओपेन(), जैसा कि पीओएसईक्स द्वारा अनिवार्य है, एक शून्य * देता है, लेकिन सी, जैसा कि आईएसओ द्वारा अनिवार्य है, कहता है कि एक शून्य * किसी ऑब्जेक्ट के लिए एक सूचक है और ऐसा सूचक एक फ़ंक्शन पॉइंटर के साथ आवश्यक रूप से संगत नहीं है।

तथ्य यही है कि समारोह और संकेत आपत्ति के बीच किसी भी रूपांतरण एक (स्वाभाविक गैर पोर्टेबल) कार्यान्वयन विस्तार के रूप में माना जाना चाहिए, और एक सीधा रूपांतरण के लिए कोई 'सही' रास्ता मौजूद है, के बाद से इस संबंध में पॉसिक्स और आईएसओ मानकों एक-दूसरे के विरोधाभास हैं।

मानक जो विरोधाभास मौजूद हैं और वहां कौन से मानक दस्तावेज हैं, वैसे भी विशेष रूप से सार्थक नहीं हो सकते हैं। यहां ओलिच ड्रेपर ओपन ग्रुप और उनके "विनिर्देशों" के लिए उनके विवाद के बारे में लिख रहे हैं।

http://udrepper.livejournal.com/8511.html

इसी भावना रॉड्रिगो से जुड़े हुए पोस्ट में व्यक्त किया जाता है।

कारण मैं इस परिवर्तन कर दिया है वास्तव में अधिक से अधिक अनुरूप होना करने के लिए नहीं है (यह अच्छा है, लेकिन कोई के बाद से बिना किसी कारण के वर्ष व्यवहार के बारे में शिकायत)।

इस पर ध्यान देने के बाद, मैं सवाल का उचित जवाब का मानना ​​है के रूप में आप यह इस संबंध में कोई सही या dlopen() के लिए गलत व्यवहार है कि वहाँ है नहीं कहते। तर्कसंगत रूप से, एक बार एक खोज ने एक प्रतीक को हल कर लिया है, यह अब अपरिभाषित नहीं है और बाद की खोजों में गतिशील लोडर पहले से परिभाषित प्रतीक को हल करने का प्रयास नहीं करेगा।

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

main.c

#include <dlfcn.h> 

void say_hi(void); 

int main(void) { 
    void* symbols_b = dlopen("./dyload.so", RTLD_NOW | RTLD_GLOBAL); 
    /* uh-oh, forgot to define this function */ 
    /* better remember to define it in dyload.so */ 
    say_hi(); 
    return 0; 
} 

dyload।सी

#include <stdio.h> 
void say_hi(void) { 
    puts("dyload.so: hi"); 
} 

संकलित और चलाएं।

gcc-4.8 main -fpic -ldl -Wl,--unresolved-symbols=ignore-all -o main 
gcc-4.8 dyload.c -shared -fpic -o dyload.so 
$ ./main 
dyload.so: hi 

ध्यान दें कि मुख्य निष्पादन योग्य स्वयं को पीआईसी के रूप में संकलित किया गया था।

+0

यही वह है जिसे मैं एक उत्कृष्ट उत्तर कहता हूं! – paulotorrens

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