.init
/ .fini
घटाया नहीं है। यह अभी भी ईएलएफ मानक का हिस्सा है और मैं कहूंगा कि यह हमेशा के लिए होगा। कोड इन .init
/ .fini
लोडर / रनटाइम-लिंकर द्वारा चलाया जाता है जब कोड लोड / अनलोड किया जाता है। प्रत्येक ईएलएफ लोड पर (उदाहरण के लिए एक साझा पुस्तकालय) कोड .init
चलाया जाएगा। यह उसी तंत्र का उपयोग करना अभी भी संभव है, जैसा कि उसी चीज़ के बारे में प्राप्त करना __attribute__((constructor))/((destructor))
। यह पुराना स्कूल है, लेकिन इसके कुछ फायदे हैं।
.ctors
/ .dtors
उदाहरण के लिए तंत्र को सिस्टम-आरटीएल / लोडर / लिंकर-स्क्रिप्ट द्वारा समर्थन की आवश्यकता होती है। यह सभी प्रणालियों पर उपलब्ध निश्चित से बहुत दूर है, उदाहरण के लिए गहराई से एम्बेडेड सिस्टम जहां कोड नंगे धातु पर निष्पादित होता है। Ie भले ही __attribute__((constructor))/((destructor))
GCC द्वारा समर्थित हो, यह निश्चित नहीं है कि इसे चलाने के लिए लिंकर तक और इसे चलाने के लिए लोडर (या कुछ मामलों में, बूट-कोड) पर चलना होगा। उपयोग करने के लिए .init
/ .fini
बजाय, सबसे आसान तरीका लिंकर झंडे का उपयोग करना है: -init -fini (यानी जीसीसी कमांड लाइन से, सिंटैक्स होगा -Wl -init my_init -fini my_fini
)।
दोनों तरीकों का समर्थन करने वाले सिस्टम पर, एक संभावित लाभ यह है कि कोड .init
पहले चलाया जाता है .ctors
और .fini
बाद में कोड .dtors
। यदि आदेश प्रासंगिक है तो कम से कम एक क्रूड लेकिन आसान तरीका है जो इनिट / एग्जिट फ़ंक्शंस के बीच अंतर करता है।
एक बड़ी कमी यह है कि आप आसानी से प्रत्येक लोड करने योग्य मॉड्यूल के प्रति एक _init
और एक से अधिक _fini
कार्य नहीं कर सकते हैं और संभवतः .so
प्रेरित से अधिक में कोड को टुकड़े करना होगा । एक और यह है कि ऊपर वर्णित लिंकर विधि का उपयोग करते समय, कोई मूल _init और _fini
डिफ़ॉल्ट फ़ंक्शन (द्वारा प्रदान crti.o
) को प्रतिस्थापित करता है । यह वह जगह है जहां आमतौर पर सभी प्रकार के आरम्भिकरण होते हैं (लिनक्स पर यह वह जगह है जहाँ वैश्विक चर असाइनमेंट को आरंभीकृत किया जाता है)। चारों ओर एक रास्ता यहाँ वर्णित है
ऊपर दिए गए लिंक में ध्यान दें कि मूल _init()
में कैस्केडिंग की आवश्यकता नहीं है क्योंकि यह अभी भी जगह में है। call
इनलाइन विधानसभा तथापि में 86-स्मरक और एक समारोह विधानसभा (उदाहरण के लिए एआरएम) की तरह कई अन्य आर्किटेक्चर के लिए पूरी तरह से अलग दिखेगा से फोन कर रहा है। Ie कोड पारदर्शी नहीं है।
.init
/ .fini
और .ctors
/ .detors
तंत्र समान हैं, लेकिन काफी नहीं। में कोड .init
/ .fini
रन "जैसा है"। यानी आपके पास .init
/ में कई कार्य हो सकते हैं .fini
, लेकिन कई छोटी .so
फ़ाइलों में कोड को तोड़ने के बिना पूरी तरह से पारदर्शी सी में उन्हें पूरी तरह से पारदर्शी रूप से वहां रखना मुश्किल है ।
.ctors
/ .dtors
से अलग आयोजित किए जाते हैं .init
/ .fini
। .ctors
/ .dtors
अनुभाग दोनों फ़ंक्शन के साथ संकेत के साथ सिर्फ टेबल हैं, और "कॉलर" एक सिस्टम-प्रदत्त लूप है जो प्रत्येक फ़ंक्शन को अप्रत्यक्ष रूप से कॉल करता है। यानी लूप-कॉलर आर्किटेक्चर विशिष्ट हो सकता है, लेकिन जैसा कि यह सिस्टम का हिस्सा है (यदि यह सभी पर मौजूद है) तो कोई फर्क नहीं पड़ता।
निम्नलिखित स्निपेट .ctors
फ़ंक्शन सरणी में नए फ़ंक्शन पॉइंटर्स जोड़ता है , मुख्य रूप से उसी तरह से __attribute__((constructor))
होता है (विधि के साथ सह-अस्तित्व हो सकता है) __attribute__((constructor)))
।
#define SECTION( S ) __attribute__ ((section ( S )))
void test(void) {
printf("Hello\n");
}
void (*funcptr)(void) SECTION(".ctors") =test;
void (*funcptr2)(void) SECTION(".ctors") =test;
void (*funcptr3)(void) SECTION(".dtors") =test;
एक फ़ंक्शन पॉइंटर्स को एक पूरी तरह से अलग-अलग स्व-आविष्कृत अनुभाग में भी जोड़ सकता है। एक संशोधित लिंकर स्क्रिप्ट और लोडर .ctors
/ .dtors
लूप की नकल करने वाले एक अतिरिक्त फ़ंक्शन की आवश्यकता होती है। लेकिन इसके साथ ही कोई भी निष्पादन आदेश पर बेहतर नियंत्रण प्राप्त कर सकता है, इन-तर्क और रिटर्न कोड हैंडलिंग एटा (उदाहरण के लिए एक C ++ परियोजना में, यह वैश्विक निर्माणकर्ताओं के पहले या बाद में चलने वाली किसी चीज़ की आवश्यकता में उपयोगी होगा)।
__attribute__((constructor))/((destructor))
जहां संभव हो, मैं पसंद करूंगा , यह एक सरल और सुरुचिपूर्ण समाधान है यहां तक कि यह धोखा देने जैसा लगता है। अपने जैसे नंगे-धातु कोडर के लिए, यह हमेशा एक विकल्प नहीं है।
पुस्तक लिंकर्स और लोडर में कुछ अच्छे संदर्भ ।
#define __attribute__(x)
) के लिए आसान बनाते हैं । यदि आपके पास कई गुण हैं, उदाहरण के लिए__attribute__((noreturn, weak))
, यह "मैक्रो आउट" के लिए कठिन होगा यदि केवल ब्रैकेट्स का एक सेट था।