"স্বয়ংক্রিয় স্ট্যাক সম্প্রসারণ" কী?


13

ম্যান পেজগুলিতে getrlimit (2) এর নিম্নলিখিত সংজ্ঞা রয়েছে:

RLIMIT_AS প্রসেসটির ভার্চুয়াল মেমরির সর্বোচ্চ আকার (অ্যাড্রেস স্পেস) বাইটে tes এই সীমাটি ব্র্যাক (2), এমএম্যাপ (2) এবং ম্রেম্যাপ (2) এর কলগুলিকে প্রভাবিত করে, যা এই সীমাটি ছাড়িয়ে যাওয়ার পরে এনওএমএম ত্রুটি নিয়ে ব্যর্থ হয়। এছাড়াও স্বয়ংক্রিয় স্ট্যাকের সম্প্রসারণ ব্যর্থ হবে (এবং সিগলসট্যাক (2)) এর মাধ্যমে কোনও বিকল্প স্ট্যাক উপলব্ধ না করা থাকলে প্রক্রিয়াটি মেরে ফেলা এমন একটি SIGSEGV উত্পন্ন করবে। যেহেতু মানটি দীর্ঘ, 32-বিট দীর্ঘ মেশিনগুলিতে হয় এই সীমাটি সর্বাধিক 2 জিআইবি হয়, বা এই সংস্থানটি সীমাহীন।

এখানে "স্বয়ংক্রিয় স্ট্যাক সম্প্রসারণ" বলতে কী বোঝায়? একটি লিনাক্স / ইউনিক্স পরিবেশে স্ট্যাক কি প্রয়োজনীয় হিসাবে বৃদ্ধি পায়? যদি হ্যাঁ, সঠিক প্রক্রিয়া কি?

উত্তর:


1

হ্যাঁ স্ট্যাকগুলি গতিশীলভাবে বৃদ্ধি পায়। স্ট্যাকটি স্তূপের দিকে নিচের দিকে বাড়ছে মেমরির শীর্ষে।

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

স্তূপটি উপরের দিকে বৃদ্ধি পায় (যখনই আপনি মলোক করেন) এবং নতুন ফাংশন যখন বলা হয় তখন স্ট্যাকটি নীচের দিকে বৃদ্ধি পায়। প্রোগ্রামটির বিএসএস বিভাগের ঠিক উপরে গাদা উপস্থিত রয়েছে। যার অর্থ আপনার প্রোগ্রামের আকার এবং এটি যেভাবে memoryেকে মেমরি বরাদ্দ করে সেই প্রক্রিয়াটির জন্য সর্বাধিক স্ট্যাকের আকারকেও প্রভাবিত করে। সাধারণত স্ট্যাকের আকারটি সীমাহীন থাকে (অবধি গাদা এবং স্ট্যাকের অঞ্চলগুলি মিলিত হয় এবং / অথবা ওভাররাইট) যা স্ট্যাককে ওভারফ্লো এবং SIGSEGV দেয় :-)

এটি কেবল ব্যবহারকারী প্রক্রিয়াগুলির জন্য, কার্নেল স্ট্যাক সর্বদা স্থির হয় (সাধারণত 8 কেবি)


"সাধারণত স্ট্যাকের আকারটি সীমাহীন হয়" না, সাধারণত এটি 8Mb ( ulimit -s) দ্বারা সীমাবদ্ধ হয় ।
এডি_এএম

হ্যাঁ আপনি বেশিরভাগ সিস্টেমে ঠিকই আছেন। আপনি শেলের ইউলিমিট কমান্ডটি পরীক্ষা করে দেখছেন, যদি তাই হয় তবে স্ট্যাকের আকারের একটি কঠোর সীমা রয়েছে, যা সীমাহীন (ulimit -Hs)। যাইহোক, সেই বিন্দুটি ছিল স্ট্যাকটি এবং চাপাগুলি বিপরীত দিকে বেড়ে যায় grows
সন্তোষ

তারপরে কীভাবে "স্বয়ংক্রিয় সম্প্রসারণ" "স্ট্যাকের উপাদানগুলিকে ধাক্কা দেওয়ার" থেকে আলাদা? আপনার ব্যাখ্যা থেকে আমি অনুভব করি যে তারা একই রকম। এছাড়াও, আমার কাছে মনে হয়েছিল স্ট্যাক এবং হিপগুলির সূচনা পয়েন্টগুলি 8MB এর চেয়ে বেশি, সুতরাং স্ট্যাকটি যতটা প্রয়োজন তত বাড়তে পারে (বা এটি স্তূপটি আঘাত করে)। এটা কি সত্যি? যদি হ্যাঁ, অপারেটিং সিস্টেমটি কোথায় কোথায় গাদা এবং স্ট্যাকটি রাখবে সে বিষয়ে সিদ্ধান্ত নিয়েছে?
লাউড্যান্ডলেকার

সেগুলি একই, তবে স্ট্র্যাকসগুলির একটি নির্দিষ্ট আকার না থাকে যদি না আপনি রিলিমিট ব্যবহার করে আকারটিকে কঠোরভাবে সীমাবদ্ধ করেন। স্ট্যাকটি ভার্চুয়াল মেমরি অঞ্চলের শেষে স্থাপন করা হয়, এবং হিপ কার্যকরভাবে কার্যকর করতে সক্ষম * এর ডেটা বিভাগে আফিম * এআর টেক থাকে।
সন্তোষ

আমি বুঝতে পারি, ধন্যবাদ। তবে, আমি "স্ট্যাকের স্থির আকার নেই" অংশটি পাই বলে মনে করি না। যদি তা হয় তবে 8 এমবি নরম সীমাটি কী?
লাউডএন্ডস্লেয়ার

8

লিনাক্সে, সঠিক পদ্ধতিটি এখানে দেওয়া হয়েছে: বেনামে ম্যাপিংগুলিতে একটি পৃষ্ঠা ত্রুটি পরিচালনা করার ক্ষেত্রে আপনি এটি পরীক্ষা করে দেখেছেন যে এটি একটি "বর্ধিত বরাদ্দ" কিনা যা আপনার স্ট্যাকের মতো প্রসারিত করা উচিত whether যদি ভিএম এরিয়া রেকর্ডটি বলে যে আপনার উচিত, তবে আপনি স্ট্যাকটি প্রসারিত করার জন্য সূচনা ঠিকানাটি সামঞ্জস্য করুন।

ঠিকানার উপর নির্ভর করে কোনও পৃষ্ঠার ত্রুটি দেখা দিলে এটি স্ট্যাক বিস্তারের মাধ্যমে পরিবেশন করা যেতে পারে (এবং ফল্টটি বাতিল করা হয়েছে)। ভার্চুয়াল মেমরির জন্য এই "ফল্টের নীচে ক্রমবর্ধমান" আচরণের জন্য সিস্কেলটিতে MAP_GROWSDOWNপতাকাটি পাঠানো স্বেচ্ছাচারী ব্যবহারকারী প্রোগ্রামগুলির দ্বারা অনুরোধ করা যেতে পারে mmap

আপনি কোনও ব্যবহারকারী প্রোগ্রামেও এই প্রক্রিয়াটির সাথে গোলমাল করতে পারেন:

#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এবং আসল অঞ্চলটি কীভাবে বৃদ্ধি পেয়েছে তা দেখুন look


মেমরি অঞ্চল MAP_GROWSDOWN এর মাধ্যমে বেড়ে গেলেও মূল মেম্ব এবং পেজ_সাইজের জন্য মুনম্যাপটি কল করা ঠিক আছে কি? আমি হ্যাঁ অনুমান করি, কারণ অন্যথায় এটি ব্যবহার করা খুব জটিল এপিআই হবে, তবে ডকুমেন্টেশন এ বিষয়ে স্পষ্ট করে কিছু বলে না
i.petruk

2
MAP_GROWSDOWN ব্যবহার করা উচিত নয়, এবং গ্লিবসি থেকে সরানো হয়েছে (এর জন্য lwn.net/Articles/294001 দেখুন )।
কলিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.