• 09. 동적 할당 영역과 시스템 호출

    2021. 9. 20.

    by. ahntree

    728x90

    프로세스의 동적 할당 영역exit(), wait() 시스템 호출을 깊이 있게 살펴보자.

     

     

     

    1. 프로세스의 동적 할당 영역

    프로세스는 총 4가지 영역으로 이루어져 있다. 이를 크게 정적 할당 영역과 동적 할당 영역으로 나눌 수 있다.

     

    정적 할당 영역에는 코드 영역과 데이터 영역이 있다. 코드 영역은 프로그램의 본체가 있는 곳이고, 데이터 영역은 프로그램이 사용하려고 정의한 변수와 데이터가 있는 곳이다. 이 두개의 영역은 프로세스가 실행되기 직전에 위치와 크기가 결정되고 실행되는 동안 변하지 않는다.

     

    동적 할당 영역에는 스택 영역과 힙 영역이 있다. 이 둘을 좀 더 자세히 살펴보자.

     

     

    스택 영역

    스택을 이해하기 위해 다음 코드를 살펴보자.

     

    int main() {
      int a = 1, b = 2;
      printf("main %d %d\n", a b);
      add(a, b);
      // 1번 지점
      exit();
    }
    
    add(int c, int d) {
      mul(c, d);
      // 2번 지점
      printf("add %d\n", c+d);
    }
    
    mul(int e, int f) {
      printf("mul %d\n", e*f);
    }

     

    스택은 함수 호출 시 2가지 작업을 구현하기 위해 사용된다.

     

    • 호출한 함수가 종료되면 함수를 호출하기 전 코드로 되돌아와야 한다. 이 때 되돌아올 메모리의 주소를 스택에 저장한다. 위의 코드에서 1번 지점은 add 함수의 실행이 끝난 후, 2번 지점은 mul 함수의 실행이 끝난 후 되돌아와야 할 지점이다. 이 위치를 스택에 저장한다.
    • 변수 사용 범위에 영향을 미치는 영역(scope)을 구현할 때도 스택을 사용한다. 변수는 전역 변수지역 변수로 나뉘는데, 지역 변수의 경우 함수가 호출될 때만 사용되다가 함수가 종료되면 사용하던 공간을 반환해야 하기 때문에 스택에 저장한다.

     

    이를 바탕으로 위의 코드에서 스택을 사용하는 과정을 살펴보자.

     

    1. main 함수가 add 함수를 호출하면 스택에 되돌아올 위치 정보(1번 지점)add 함수에서 사용하는 지역 변수 c, d를 스택에 넣는다.
    2. add 함수가 mul 함수를 호출하면 스택에 되돌아올 위치 정보(2번 지점)mul 함수에서 사용하는 지역 변수 e, f를 스택에 넣는다.
    3. mul 함수의 호출이 끝나면 스택에서 pop한다. 2번 지점으로 돌아와서 실행을 이어나간다.
    4. add 함수의 호출이 끝나면 스택에서 pop한다. 1번 지점으로 돌아와서 실행을 이어나간다.

     

    스택의 크기는 함수의 호출 횟수와 관련이 있다. 함수를 많이 호출한다는 건 그만큼 많은 지역 변수와 메모리 주소가 저장되어야 함을 의미하기 때문이다. 그래서 스택의 크기는 스레드가 작동하는 동안 동적으로 변할 수밖에 없다. 유저의 입력에 따라 함수의 호출 횟수는 동적으로 변하기 때문이다.

     

     

    힙 영역

    힙은 동적으로 할당되는 변수 영역이다. 대부분의 데이터는 데이터 영역에 할당되고 크기도 고정적이지만 일부 데이터는 프로그램이 실행되는 동안 할당된다. 대표적이 경우가 malloc 함수이다.

     

    main() {
      int sarr[50];
      int *darr;
    
      darr = (int*)malloc(sizeof(int) * 50);
    
      free(darr);
    }

     

    sarrdarr 모두 50개짜리 정수 배열이다. 차이점이 있다면 sarr는 변수를 선언할 때 이미 크기가 정해졌지만 darr는 변수를 선언할 때는 크기를 가지고 있지 않다가 malloc 함수를 통해 동적으로 크기를 할당받은 것이다. 그래서 sarr는 데이터 영역에, darr는 힙 영역에 데이터가 저장된다. 힙 영역에 데이터를 저장하면 어떤 점이 좋을까?

     

    먼저, 데이터의 크기를 나중에 정할 수 있다. 사용자가 프로그램을 통해 어느 정도의 데이터를 사용할 지 모르는 상태에서 메모리 부족을 방지하고자 무턱대고 큰 영역을 할당한다면 메모리의 낭비가 있을 수밖에 없다. 힙 영역에 데이터를 저장하면 변수를 선언한 이후에 크기를 할당할 수 있으므로 이런 종류의 낭비를 피할 수 있다.

     

    메모리 관리를 효율적으로 할 수 있다. 위 코드를 보면 free 함수를 통해 darr 변수에 할당된 메모리 영역을 해제하고 있다. 이처럼 더 이상 사용하지 않은 영역을 반환함으로써 메모리를 관리할 수 있다.

     

     

     

    2. exit()와 wait() 시스템 호출

    exit() 시스템 호출

     

    main() {
      printf("Hello \n");
      exit(0);
    }

     

    C 언어를 배울 때 처음 접하게 되는 코드이다. 마지막 줄에 exit 혹은 return 문을 사용하는 것은 자식 프로세스가 끝났음을 부모 프로세스에게 알려주기 위함이다. 부모 프로세스에게 알려주는 이유는 자식 프로세스가 사용하던 자원을 빨리 회수할 수 있도록 하기 위함이다.

     

    전달하는 인자를 통해 프로세스가 정상 종료되었는지를 알려줄 수 있다. 0이면 정상 종료, -1이면 비정상 종료이다.

     

     

    wait() 시스템 호출

    운영체제는 부모 프로세스가 자식 프로세스보다 먼저 종료됨으로써 고아 프로세스가 생기는 것을 막기 위해 wait() 시스템 호출을 사용한다. wait() 시스템 호출은 자식 프로세스가 종료되기를 기다렸다가 종료되면 다음 문장을 실행한다.

    728x90

    '운영체제' 카테고리의 다른 글

    11. 스케줄링 시 고려 사항  (0) 2021.09.20
    10. 스케줄링의 개요  (0) 2021.09.20
    08. 스레드  (0) 2021.09.20
    07. 프로세스의 연산  (0) 2021.09.20
    06. 프로세스 제어 블록과 문맥 교환  (0) 2021.09.20

    댓글