"स्वचालित स्टैक विस्तार" क्या है?


13

getrlimit (2) मैन पेजों में निम्नलिखित परिभाषा है:

RLIMIT_AS बाइट्स में प्रक्रिया की वर्चुअल मेमोरी (पता स्थान) का अधिकतम आकार। यह सीमा brk (2), mmap (2) और mremap (2) के लिए कॉल को प्रभावित करती है, जो इस सीमा से अधिक होने पर त्रुटि ENOMEM के साथ विफल हो जाती है। इसके अलावा स्वचालित स्टैक विस्तार विफल हो जाएगा (और एक SIGSEGV उत्पन्न करता है जो इस प्रक्रिया को मारता है यदि कोई वैकल्पिक स्टैक सिगलेटस्टैक (2) के माध्यम से उपलब्ध नहीं कराया गया है)। चूंकि मूल्य एक लंबा है, 32-बिट लंबी मशीनों के साथ या तो यह सीमा अधिकतम 2 GiB पर है, या यह संसाधन असीमित है।

यहाँ "स्वचालित स्टैक विस्तार" से क्या अभिप्राय है? क्या Linux / UNIX वातावरण में स्टैक आवश्यकतानुसार बढ़ता है? यदि हाँ, तो सटीक तंत्र क्या है?

जवाबों:


1

हां ढेर गतिशील रूप से बढ़ते हैं। ढेर स्मृति की चोटी में नीचे की ओर बढ़ रहा है।

--------------
| Stack      |
--------------
| Free memory|
--------------
| Heap       |
--------------
     .
     .

ढेर ऊपर की तरफ बढ़ता है (जब भी आप मॉलॉक करते हैं) और नए कार्यों को बुलाए जाने पर स्टैक नीचे की ओर बढ़ता है। ढेर कार्यक्रम के बीएसएस अनुभाग के ठीक ऊपर मौजूद है। जिसका अर्थ है आपके प्रोग्राम का आकार और जिस तरह से यह मेमोरी को ढेर में आवंटित करता है, उस प्रक्रिया के लिए अधिकतम स्टैक आकार को भी प्रभावित करता है। आमतौर पर स्टैक का आकार असीमित होता है (जब तक ढेर और स्टैक क्षेत्र मिलते हैं और / या ओवरराइट करते हैं जो स्टैक ओवरफ्लो और SIGSEGV :-) देगा)

यह केवल उपयोगकर्ता प्रक्रियाओं के लिए है, कर्नेल स्टैक हमेशा तय किया जाता है (आमतौर पर 8KB)


"आमतौर पर स्टैक का आकार असीमित होता है", नहीं, आमतौर पर यह 8Mb ( ulimit -s) तक सीमित होता है ।
Eddy_Em

हाँ, आप अधिकांश प्रणालियों में सही हैं। आप शेल के अलिमिट कमांड की जांच कर रहे हैं, यदि ऐसा है तो स्टैक के आकार पर एक कठिन सीमा है, जो असीमित है (ulimit -Hs)। वैसे भी, उस बिंदु को तनाव देना था कि ढेर और ढेर विपरीत दिशाओं में बढ़ता है।
संतोष

फिर "स्वचालित विस्तार" कैसे "धकेलने वाले तत्वों से ढेर" से अलग है? आपके स्पष्टीकरण से, मुझे लग रहा है कि वे समान हैं। इसके अलावा, मैंने महसूस किया कि स्टैक और हीप के शुरुआती बिंदु 8 एमबी से अधिक हैं, इसलिए स्टैक उतना ही बढ़ सकता है जितना इसकी आवश्यकता होती है (या यह ढेर को हिट करता है)। क्या यह सच है? यदि हाँ, तो ऑपरेटिंग सिस्टम कैसे तय करता है कि ढेर और स्टैक कहाँ रखें?
जोर

वे समान हैं, लेकिन स्टैक का एक निश्चित आकार नहीं है जब तक कि आप कठोर का उपयोग करके सीमा को सीमित नहीं करते हैं। स्टैक को वर्चुअल मेमोरी एरिया के अंत में रखा जाता है, और हीप एक्जीक्यूटेबल के डेटा सेग्मेंट से तुरंत * एर टीक डेटा सेगमेंट पर आ जाता है।
संतोष

मैं समझता हूं, धन्यवाद। हालांकि, मुझे नहीं लगता कि मुझे "स्टैक में निश्चित आकार नहीं है" भाग मिलता है। अगर ऐसा है, तो 8Mb सॉफ्ट लिमिट किसके लिए है?
जोर से

8

लिनक्स पर सटीक तंत्र यहां दिया गया है: अनाम मैपिंग पर एक पृष्ठ दोष को संभालने के लिए आप यह देखने के लिए जांचें कि क्या यह "बड़ा हो गया आवंटन" है जिसे आपको स्टैक की तरह विस्तारित करना चाहिए। यदि वीएम क्षेत्र रिकॉर्ड कहता है कि आपको चाहिए, तो आप स्टैक का विस्तार करने के लिए प्रारंभ पता समायोजित करें।

जब पृष्ठ दोष होता है, तो पते के आधार पर, इसे स्टैक विस्तार के माध्यम से सेवित किया जा सकता है। वर्चुअल मेमोरी के लिए यह "गलती से नीचे की ओर बढ़ रहा है" व्यवहार को मनमाने ढंग से उपयोगकर्ता कार्यक्रमों द्वारा अनुरोध किया जा सकता है, MAP_GROWSDOWNध्वज के साथ mmapsyscall को पारित किया जा सकता है।

आप इस तंत्र के साथ एक उपयोगकर्ता कार्यक्रम में भी गड़बड़ कर सकते हैं:

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

int main() {
        long page_size = sysconf(_SC_PAGE_SIZE);
        void *mem = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_GROWSDOWN|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
        if (MAP_FAILED == mem) {
                perror("failed to create growsdown mapping");
                return EXIT_FAILURE;
        }

        volatile char *tos = (char *) mem + page_size;

        int i;
        for (i = 1; i < 10 * page_size; ++i)
                tos[-i] = 42;

        fprintf(stderr, "inspect mappping for originally page-sized %p in /proc... press any key to continue...\n", mem);
        (void) getchar();

        if (munmap(mem, page_size))
                perror("failed munmap");

        return EXIT_SUCCESS;
}

जब यह संकेत देता है कि आप कार्यक्रम के माध्यम से ( ps) के माध्यम से पीआईडी /proc/$THAT_PID/mapsको देखें और देखें कि मूल क्षेत्र कैसे विकसित हुआ है।


यदि मूल क्षेत्र MAP_GROWSWOWN के माध्यम से हो गया है, तो भी मूल मेम और पेज_साइज़ के लिए मुनमैप को कॉल करना ठीक है? मैं हाँ मानता हूं, क्योंकि अन्यथा यह उपयोग करने के लिए एक बहुत ही जटिल एपीआई होगा, लेकिन प्रलेखन इस मामले पर स्पष्ट रूप से कुछ नहीं कहता है
i.petruk

2
MAP_GROWSDOWN का उपयोग नहीं किया जाना चाहिए, और इसे glibc से हटा दिया गया है (देखें lwn.net/Articles/294001 क्यों)।
कोलिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.