Stack Size 조절 Linux Programming


Linux 시스템에서 프로그램을 개발할 때 local 변수와 global 변수 등을 사용해서 데이터 처리를 한다. 이 때 global 변수는 힙(heap) 영역에 할당되는 반면, local 변수는 스택(stack) 영역에 할당됩니다. Linux에서는 User 당 허용 가능한 stack size가 지정되어 있는데 기본적으로 8192K입니다. 이 정보는 ulimit -a 명령어로 확인 가능하면, 단위(unit)는 Kilo byte 입니다. 간혹 개발 작업을 진행하면서 memory access 시도도 아닌 곳 즉 함수 호출 등에서 segmentation fault를 겪어 보셨을 것입니다. 이 에러가 발생한 이유는 stack이 최대 허용 가능한 size까지 사용됨으로 인해서 함수 정보 역시 stack에 쌓이게 될때 더 이상 허용해주지 않음으로써 segmentation fault(SIGSEGV signal 전송)가 발생된 것입니다. 그러면 이러한 문제를 어떻게 해결해야 할까요?

우선 답은 3가지 입니다.

첫째, 흔히 local 변수를 많이 사용하는 경우는 thread 모델 프로그래밍을 할 경우에 동기화에 대한 lock을 피하기 위해서 사용하곤 합니다. 이때 동기화를 피하기 위해서 stack을 남발하기 쉬운데, stack과 heap 할당에 대해 적절히 조절하시는 방법이 있습니다. 물론 이건 프로그래머가 조심해야 하는 수밖에 없습니다.

두번째와 세번째는 stack size를 크게 만드는 작업입니다. 단, 두번째는 명령어를 사용하는 것이고, 세번째는 system call을 사용하는 방법입니다.
우선 방법 먼저 설명하도록 하겠습니다.
두번째 명령어를 사용하는 방식은 ulimit -s (stack size)를 사용해서 변경할 수 있다.
세번째 system call은 getrlimit/setrlimit를 사용해서 변경 가능하다. 간단하게 10M로 변경하는 예제 코드를 작성하면, 다음과 같다.

#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>

int main( void )
{
        struct rlimit rlim;

        getrlimit( RLIMIT_STACK, &rlim );
        printf( "Current Stack Size : [%d] Max Current Stack Size : [%d]\n, rlim.rlim_cur, rlim.rlim_max );
        rlim.rlim_cur = (1024 * 1024 * 10);
        rlim.rlim_max = (1024 * 1024 * 10);
        setrlimit( RLIMIT_STACK, &rlim );
        printf( "Current Stack Size : [%d] Max Current Stack Size : [%d]\n, rlim.rlim_cur, rlim.rlim_max );

        return 0;
}

그럼 이 두 방식에는 무슨 차이점이 있을까요? 가장 큰 차이점은 두번째는 해당 프로그램을 다른 시스템에 적용시킬때마다 실행 환경을 변경하기 위해 항상 stack size에 대한 조절을 해줘야 한다는 점입니다. 이 방법은 너무 귀찮을 것입니다. 반면, system call을 사용하는 방식은 프로그램에서 변경하기 때문에, 따로 설정을 할 필요 없이 해당 프로그램 실행만으로 실행 환경을 프로그램상에서 조절하게 된다. 즉 다른 시스템에 이식하려 한다면, 세번째 방식으로 프로그램상에서 자신의 실행환경을 맞추는 법이 좀더 훌륭한 방법이라고 할 수 있다.


핑백

덧글

  • 히언 2010/07/30 12:58 #

    좋은 글이라 핑백합니다~
※ 로그인 사용자만 덧글을 남길 수 있습니다.