“자동 스택 확장”이란 무엇입니까? mmap (2) 및 mremap

getrlimit (2) 는 매뉴얼 페이지에서 다음 정의를 갖습니다.

RLIMIT_AS
프로세스의 가상 메모리 (주소 공간)의 최대 크기 (바이트). 이 제한은 brk (2), mmap (2) 및 mremap (2) 호출에 영향을 미치며이 제한을 초과하면 오류 ENOMEM과 함께 실패합니다. 또한 자동 스택 확장 이 실패합니다 (sigaltstack (2)를 통해 대체 스택을 사용할 수없는 경우 프로세스를 종료하는 SIGSEGV 생성). 값이 길기 때문에 길이가 32 비트 인 시스템에서는이 제한이 최대 2GiB이거나이 리소스가 무제한입니다.

여기서 “자동 스택 확장”이란 무엇입니까? Linux / UNIX 환경의 스택이 필요에 따라 증가합니까? 그렇다면 정확한 메커니즘은 무엇입니까?



답변

예, 스택이 동적으로 커집니다. 스택은 메모리 상단에 있으며 힙쪽으로 아래쪽으로 자랍니다.

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

malloc을 할 때마다 힙이 위쪽으로 커지고 새 함수가 호출 될 때마다 스택이 아래쪽으로 커집니다. 힙은 프로그램의 BSS 섹션 바로 위에 있습니다. 즉, 프로그램 크기와 메모리를 힙으로 할당하는 방식도 해당 프로세스의 최대 스택 크기에 영향을 미칩니다. 일반적으로 스택 크기는 무제한입니다.

이것은 사용자 프로세스에만 해당됩니다. 커널 스택은 항상 고정되어 있습니다 (보통 8KB).


답변

정확한 메커니즘은 리눅스, 여기에 주어진 :에 익명 매핑에 페이지 오류를 처리 하면 그것은 “어른이 할당 않는다”인지 확인 당신이 스택처럼 확대해야한다고는. 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;
}

메시지가 표시되면 (을 통해 ps) 프로그램의 pid를 찾고 /proc/$THAT_PID/maps원래 영역이 어떻게 성장했는지 확인하십시오.


답변