2012-03-29 13 views
5

In gcc doc एक कारण section प्रयोग करने के लिए दिया जाता है में एक चर डालने में बिंदु हो सकता है। यही कारण है to map to special hardware है। लेकिन इस प्रतीत हो रहा है नहीं मेरे मामले।
वास्तव में क्या __attribute__ ((खंड ("स्टैक"))? के साथ "स्टैक" खंड

तो मैं एक साझा पुस्तकालय है कि हम अपने परियोजना पर उपयोग संशोधित करने के लिए एक कार्य दे दिया है। यह एक लिनक्स पुस्तकालय है। पुस्तकालय है कि मुझे puzzeles में चर घोषणाओं है। वे (मोटे तौर पर इस तरह दिखेगा):

static int my_var_1 __attribute__((section("STACK"))) = 0; 


अद्यतन 1:
( __attribute__((section("STACK"))))



अद्यतन 2 को इस तरह से परिभाषित चर के एक दर्जन से अधिक कर रहे हैं:
my_var_1 एक निरंतर नहीं है।

my_var_1 = atoi(getenv("MY_VAR_1") ? getenv("MY_VAR_1") : "0"); 

पुस्तकालय में बाद में इसे इस तरह प्रयोग किया जाता है:

inline void do_something() __attribute__((always_inline)); 
inline void do_something() 
{ 
    if (my_var_1) 
    do_something_else(); 
} 


क्या __attribute__((section("STACK"))) का उपयोग करने में बिंदु हो सकता है my_var_1 आरंभीकरण के दौरान कोड में बदला जा सकता है? मैं समझता हूं कि section संकलक को विशेष खंड में एक चर डालने के लिए कहता है। हालांकि static int को "स्टैक" सेक्शन में डालने में क्या बात हो सकती है?


अद्यतन 3
ये लाइनें readelf -t my_lib.so

[23] .got.plt 
     PROGBITS   00000000002103f0 00000000000103f0 0 
     00000000000003a8 0000000000000008 0     8 
     [0000000000000003]: WRITE, ALLOC 
    [24] .data 
     PROGBITS   00000000002107a0 00000000000107a0 0 
     00000000000000b0 0000000000000000 0     16 
     [0000000000000003]: WRITE, ALLOC 
    [25] STACK 
     PROGBITS   0000000000210860 0000000000010860 0 
     00000000000860e0 0000000000000000 0     32 
     [0000000000000003]: WRITE, ALLOC 
    [26] .bss 
     NOBITS   0000000000296940 0000000000096940 0 
     0000000000000580 0000000000000000 0     32 
     [0000000000000003]: WRITE, ALLOC 


अद्यतन 4
साझा लाइब्रेरी के लेखक से जानकारी प्राप्त करने प्रबंधित से उत्पादन से अंश हैं । __attribute__((section("STACK"))) जोड़ा गया था क्योंकि वह सोलारिस पर लाइब्रेरी बनाने में कामयाब नहीं था। फिर उसने यह कामकाज पाया। वैकल्पिक हल करने से पहले my_var_1 की परिभाषा की तरह था:

int my_var_1 = 0; 

और सब कुछ ठीक था। फिर वह इसे बदल के बाद से my_var_1 वास्तव में केवल इस अनुवाद इकाई में की जरूरत थी:

static int my_var_1 = 0; 

और वह बदलाव के बाद वह सोलारिस पर पुस्तकालय का निर्माण नहीं हो सकी। तो उन्होंने __attribute__((section("STACK"))) जोड़ा और इससे किसी भी तरह मदद मिली।


+0

क्या आपकी परियोजना सामान्य x86 मशीन पर चलती है, या यह चिप (एसओसी) पर एआरएम सिस्टम की तरह कुछ है? क्या आप एक लिंकर स्क्रिप्ट पा सकते हैं (एलडी द्वारा उपयोग किया जाता है, और इसलिए आमतौर पर ".ld" के साथ समाप्त होता है)? इससे स्पष्ट रूप से स्टैक अनुभाग को स्मृति के क्षेत्र में रखा जाएगा, इसलिए उस लिंकर स्क्रिप्ट को और कुछ सुराग मिलेगा। – gbulmer

+0

कार्यक्रम सामान्य x64_86 सर्वर और एचपी-यूएक्स Itanium2 पर प्रयोग किया जाता है। कोई एआरएम सिस्टम नहीं। –

+0

आपके प्रश्न के लिए मशीनों के बारे में जानकारी जोड़ने लायक हो सकता है। मैं कल्पना कर सकता हूं कि Itanium2 _might_ कुछ ट्रिगर करता है (मुझे इसके बारे में बहुत कम पता है, लेकिन यह अलग है :-) – gbulmer

उत्तर

5

पहले STACK अनुभाग किसी भी चल रहे कार्य का ढेर नहीं होगा।

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

अन्य समाधान, कुछ विकास पोस्ट-लिंक स्क्रिप्ट सभी STACK सेक्शन 1 को सेट करेगा: एक विकास सॉफ्टवेयर हमेशा do_something_else() करेगा। और जारी सॉफ़्टवेयर 0.

का डिफ़ॉल्ट मान रख सकता है यदि STACK अनुभाग में अन्य चर हैं, तो डेवलपर उन्हें स्मृति में बंद रखना चाहता है। STACK अनुभाग में सभी वैरिएबल एक दूसरे के पास होंगे। शायद एक कैश अनुकूलन?

+0

मैंने आपके सुझाव 'अपडेट 2) को आपके सुझाव' अन्य समाधान, कुछ विकास पोस्ट-लिंक स्क्रिप्ट के बारे में स्पष्ट करने के लिए संपादित किया। ..'। क्षमा करें, मुझे यह उल्लेख करना चाहिए था कि 'my_var_1 स्थिर नहीं है'। –

+0

@skwllsp एक लिंकर स्क्रिप्ट है? एक लिंकर स्क्रिप्ट के बिना एक अनुभाग केवल उसी क्षेत्र में सभी चर समूह को समूहित करने में मदद करेगा। 'पढ़िए- तुम्हारा। इसलिए' जानकारी दे सकता है जहां 'स्टैक' अनुभाग है। – Nimlar

+0

नहीं, कोई लिंकर स्क्रिप्ट नहीं है। –

1

कई कारण हो सकते हैं और विवरण के बिना बताना मुश्किल है। कुछ कारणों में हो सकता है:

  1. अनुभाग में चिह्नित स्टैक तेजी से समय तो पहुँच अन्य मेढ़े के साथ एक निकट मिलकर स्मृति को चलाने के समय में जुड़ा हुआ है। फंक्शन कॉल के दौरान स्टालों से बचने के लिए इस तरह के रैम को ढेर मैप करना समझ में आता है। अब यदि आपके पास अचानक एक वैरिएबल था जिसे बहुत अधिक एक्सेस किया गया था और आप इसे उसी तेज़ एक्सेस रैम पर मैप करना चाहते थे, जैसे स्टैक समझ में आता है।

  2. STACK चिह्नित अनुभाग को स्मृति के उस क्षेत्र में मैप किया जा सकता है जो स्मृति के अन्य हिस्सों में उपलब्ध नहीं हो सकता है। उदाहरण के लिए, बूट लोडर को RAM तक पहुंचने से पहले मेमोरी कंट्रोलर को इनिट करने की आवश्यकता होती है। लेकिन आप वास्तव में उस कोड को लिखने में सक्षम होना चाहते हैं जो सी में करता है, जिसके लिए ढेर की आवश्यकता होती है। तो आपको कुछ विशेष मेमोरी मिलती है (जैसे डेटा कैश को लिखने के लिए प्रोग्राम कैश करना) और वहां स्टैक को मैप करें ताकि आप मेमोरी कंट्रोलर को काम करने के लिए कोड चला सकें ताकि आप रैम का उपयोग कर सकें। एक बार फिर, यदि अब आपके पास ग्लोबल वेरिएबल है जो अभी भी RAM उपलब्ध होने से पहले एक्सेस किया जाना है, तो आप इसे स्टैक सेक्शन में डालने का फैसला कर सकते हैं।

एक बेहतर प्रोग्रामर कुछ और करने के लिए स्टैक खंड अगर यह न केवल ढेर के लिए प्रयोग किया जाता है नाम दिया गया होता।

0

कुछ ऑपरेटिंग सिस्टम में, प्रत्येक थ्रेड के ढेर के लिए अंतरिक्ष को संबोधित करने का एक ही क्षेत्र उपयोग किया जाता है; जब थ्रेड के बीच निष्पादन स्विच होता है, तो उस स्थान का मानचित्रण तदनुसार बदल जाता है। ऐसे प्रणालियों पर, प्रत्येक थ्रेड के पास पता स्थान के उस क्षेत्र के भीतर स्थित किसी भी स्थिर चर का अपना स्वतंत्र सेट होगा। इस तरह की पता सीमा में प्रत्येक थ्रेड के लिए अलग-अलग बनाए रखने की आवश्यकता वाले वेरिएबल्स को प्रत्येक कार्य स्विच के साथ मैन्युअल रूप से स्वैप करने की आवश्यकता से बचें।

स्टैक क्षेत्र में चर को मजबूर करने के लिए एक और कभी-कभी उपयोग स्टैक सेंटीनल (वेरिएबल्स जिन्हें आवधिक रूप से चेक किया जा सकता है यह देखने के लिए कि स्टैक ओवरफ्लो उन्हें क्लॉबर्ड किया गया हो)।

8086 और 80286 प्लेटफार्मों पर शायद तीसरा उपयोग होता है (संभवतः परिवार में इतनी चिप्स नहीं): 8086 और 80286 सेगमेंट रजिस्टरों को फिर से लोड किए बिना चार खंडों में चीजों तक कुशलता से पहुंचने तक सीमित हैं। कोड

for (n=0; n<256; n++) 
    *dest++ = xlat[*src++]; 

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