“ การขยายสแต็กอัตโนมัติ” คืออะไร?


13

getrlimit (2)มีคำจำกัดความต่อไปนี้ใน man pages:

RLIMIT_AS ขนาดสูงสุดของหน่วยความจำเสมือนของกระบวนการ (พื้นที่ที่อยู่) ในหน่วยไบต์ ขีด จำกัด นี้มีผลต่อการเรียก brk (2), mmap (2) และ mremap (2) ซึ่งล้มเหลวด้วยข้อผิดพลาด ENOMEM เมื่อเกินขีด จำกัด นี้ นอกจากนี้ยังมีการขยายตัวของสแต็คอัตโนมัติจะล้มเหลว (และสร้าง SIGSEGV ที่ฆ่ากระบวนการถ้าไม่มีสแต็คอื่นได้รับการให้บริการผ่านทาง sigaltstack (2)) เนื่องจากค่ามีความยาวบนเครื่องที่มีความยาว 32 บิตขีด จำกัด นี้จะมากที่สุดที่ 2 GiB หรือทรัพยากรนี้ไม่ จำกัด

"การขยายสแต็กอัตโนมัติ" มีความหมายอย่างไรที่นี่ สแต็กในสภาพแวดล้อม Linux / UNIX จะเติบโตตามต้องการหรือไม่? ถ้าใช่กลไกที่แน่นอนคืออะไร

คำตอบ:


1

ใช่กองเติบโตแบบไดนามิก สแต็คอยู่ด้านบนของหน่วยความจำที่เพิ่มขึ้นลงไปทางกอง

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

ฮีปจะโตขึ้น (เมื่อใดก็ตามที่คุณทำ malloc) และสแต็กจะโตขึ้นเรื่อย ๆ เมื่อเรียกฟังก์ชันใหม่ มีฮีปอยู่เหนือส่วน BSS ของโปรแกรม ซึ่งหมายความว่าขนาดของโปรแกรมของคุณและวิธีการจัดสรรหน่วยความจำในฮีปยังส่งผลต่อขนาดสแต็กสูงสุดสำหรับกระบวนการนั้น โดยปกติแล้วขนาดสแต็กจะไม่ จำกัด (จนถึงฮีปและพื้นที่สแต็คจะพบและ / หรือเขียนทับซึ่งจะทำให้สแต็กล้นและ SIGSEGV :-)

นี่เป็นเพียงกระบวนการของผู้ใช้เคอร์เนลสแต็กถูกแก้ไขเสมอ (โดยปกติ 8KB)


"โดยปกติขนาดสแต็กจะไม่ จำกัด ", ไม่, โดยปกติจะถูก จำกัด ด้วย 8Mb ( ulimit -s)
Eddy_Em

ใช่คุณถูกต้องในระบบส่วนใหญ่ คุณกำลังตรวจสอบคำสั่ง ulimit ของเชลล์ถ้าเป็นเช่นนั้นมีข้อ จำกัด อย่างหนักต่อขนาดสแต็กซึ่งไม่ จำกัด (ulimit -Hs) อย่างไรก็ตามประเด็นนั้นก็คือการเน้นว่ากองทับซ้อนและกองขึ้นในทิศทางตรงกันข้าม
Santosh

ดังนั้น "การขยายอัตโนมัติ" ต่างจาก "การผลักองค์ประกอบไปยังสแต็ก" อย่างไร จากคำอธิบายของคุณฉันรู้สึกว่ามันเหมือนกัน นอกจากนี้ฉันรู้สึกเหมือนจุดเริ่มต้นของสแต็คและฮีปนั้นมีขนาดมากกว่า 8MB ดังนั้นสแต็กสามารถเติบโตได้มากเท่าที่ต้องการ (หรือมันจะกระทบกับฮีป) มันเป็นเรื่องจริงเหรอ? ถ้าใช่ระบบปฏิบัติการตัดสินใจได้อย่างไรว่าจะวางกองและกองไว้ที่ใด
loudandclear

พวกมันเหมือนกัน แต่สแต็คไม่มีขนาดคงที่จนกว่าคุณจะ จำกัด ขนาดโดยใช้ rlimit สแต็กจะถูกวางไว้ที่ส่วนท้ายของพื้นที่หน่วยความจำเสมือนและฮีปคือเซ็กเมนต์ข้อมูลทันทีของปฏิบัติการ
Santosh

ฉันเข้าใจขอบคุณ อย่างไรก็ตามฉันไม่คิดว่าฉันจะได้รับส่วน "สแต็คไม่มีขนาดคงที่" หากเป็นเช่นนั้นขีด จำกัด ซอฟท์แวร์ขนาด 8Mb คืออะไร
loudandclear

8

กลไกที่แน่นอนจะได้รับที่นี่บน Linux ในการจัดการความผิดหน้าในแมปที่ไม่ระบุชื่อคุณตรวจสอบเพื่อดูว่าจะเป็น "โตไม่จัดสรร"ที่คุณควรขยายเช่นสแต็ค ถ้าเรคคอร์ดพื้นที่ VM บอกว่าคุณควรเลือกปรับที่อยู่เริ่มต้นเพื่อขยายสแต็ก

เมื่อเกิดความผิดพลาดของหน้าขึ้นอยู่กับที่อยู่นั้นอาจมีการให้บริการ (และความผิดพลาดที่ถูกกำหนดไว้) ผ่านการขยายสแต็ก พฤติกรรม "การเพิ่มขึ้นของความผิดพลาด" นี้สำหรับหน่วยความจำเสมือนสามารถร้องขอได้โดยโปรแกรมผู้ใช้เองโดยมีการ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;
}

เมื่อระบบแจ้งให้คุณค้นหา pid ของโปรแกรม (ผ่านps) และดู/proc/$THAT_PID/mapsเพื่อดูว่าพื้นที่ดั้งเดิมเติบโตขึ้นอย่างไร


มันเป็นการดีที่จะเรียก munmap สำหรับ mem ดั้งเดิมและ page_size แม้ว่าขอบเขตหน่วยความจำจะเพิ่มขึ้นผ่าน MAP_GROWSDOWN? ฉันคิดว่าใช่เพราะมิฉะนั้นจะเป็น API ที่ซับซ้อนมากที่จะใช้ แต่เอกสารไม่ได้พูดอะไรเกี่ยวกับเรื่องนี้อย่างชัดเจน
i.petruk

2
ไม่ควรใช้ MAP_GROWSDOWN และถูกลบออกจาก glibc (ดูlwn.net/Articles/294001สำหรับสาเหตุ)
Collin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.