• 프로세스에서 중요한 요소 → VIRT, RES, SHR
  • 현재 프로세스가 사용하고 있는 메모리와 관련된 값
  • 프로세스는 task를 의미

VIRT → task가 사용하는 virtual memory의 전체 용량을 의미

  • 프로세스에 할당된 가상 메모리 전체의 크기
  • VIRT는 프로그램이 현재 얼마나 많은 메모리를 접근할 수 있는지를 출력
  • VIRT는 물리 메모리의 사용한 공간을 의미하지는 않음
  • VIRT = SWAP + RES
  • VIRT는 실제로는 할당되지 않은 가상의 공간(swap)이기 때문에 VIRT의 해당 값이 크다고 해도 문제되지는 않음

1. VIRT의 Memory Commit

  • 프로세스가 커널로부터 사용을 예약 받은 메모리 → 프로세스는 malloc()과 같은 시스템 콜로 자신이 필요로 하는 메모리의 영역을 할당해 줄것을 요청
  • 프로세스가 요청한 내용은 커널이 가용할 수 있는 공간이 있다면 성공 메시지와 함께 해당 프로세스가 사용할 수 있도록 가상의 메모리 주소를 전달
  • malloc을 통해 할당 받은 가상 메모리는 물리 메모리에 해당 영역이 할당된 상태는 아님

2. VIRT의 malloc 테스트 코드 → malloc_test.c 파일을 생성

$ vi malloc_test.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

# define MEGABYTE 1024*1024

int main(){
    void *myblock = NULL;
    int count = 0;

    while(1){
        myblock = (void *) malloc(MEGABYTE);
        if(!myblock){
            printf("Error!");
            break;
         }
        printf("Currently allocating %d MB\n", (++count)*MEGABYTE);
        sleep(1);
    }
    exit(0);
}

# malloc_test 파일을 malloc_test 실행 파일로 만듦
$ gcc -o malloc_test malloc_test.c
$ ls -al
-rwxr-xr-x  1 root root 8520 Oct 11 17:53 malloc_test
-rw-r--r--  1 root root  395 Oct 11 17:47 malloc_test.c

3. VIRT의 malloc 테스트 실행 결과

  • malloc() 으로 메모리 영역을 요청한 후에 아무것도 하지 않음

  • top 명령으로 해당 프로세스의 변화 확인 → 시간이 지나면서 VIRT는 계속해서 높아지지만, RES는 늘어나지 않음

    # 위에서 생성한 malloc_test 실행파일 실행
    $ ./malloc_test
    Currently allocating 1 MB
    Currently allocating 2 MB
    Currently allocating 3 MB
    Currently allocating 4 MB
    Currently allocating 5 MB
    # [...생략...]
    
    # 다른 터미널로 해당 내용 확인
    $ top -b -n 1 | grep -i malloc
    65246 root      20   0   33000    348    276 S   0.0  0.0   0:00.00 malloc_test
    
    $ top -b -n 1 | grep -i malloc
    65246 root      20   0   40196    608    400 S   0.0  0.0   0:00.00 malloc_test
    
    $ top -b -n 1 | grep -i malloc
    65246 root      20   0   47392    608    400 S   0.0  0.0   0:00.00 malloc_test
    
    $ top -b -n 1 | grep -i malloc
    65246 root      20   0   55616    608    400 S   0.0  0.0   0:00.00 malloc_test



RES → task가 사용하고 있는 physical memory의 양을 의미

  • RES는 VIRT가 사용하고 있는 실제 물리 메모리의 크기
  • 일반적으로 RES는 VIRT보다 작은 값을 출력
  • RES는 실제로 메모리를 쓰고 있음
  • RES는 SWAP 값 제외
  • RES는 메모리 점유율이 높은 프로세스를 찾기 위해서는 RES 영역이 높은 프로세스를 찾아야함

1. 프로세스가 VIRT 할당 받은 메모리를 RES에 올려서 사용

  • 프로세스가 할당받은 메모리 영역에 실제로 쓰기 작업을 하면 Page fault가 발생
  • Page fault가 발생하면 커널은 실제 물리 메모리에 프로세스의 가상 메모리 공간을 매핑 → Page Table이라고 불리는 커널의 전역 변수로 관리
  • 물리 메모리에 바인딩된영역이 RES로 계산

2. RES의 malloc 테스트 → 이전의 malloc_test.c 파일을 수정

$ vi malloc_test.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

# define MEGABYTE 1024*1024

int main(){
    void *myblock = NULL;
    int count = 0;

    while(1){
        myblock = (void *) malloc(MEGABYTE);
        if(!myblock){
            printf("Error!");
            break;
         }
        printf("Currently allocating %d MB\n", (++count)*MEGABYTE);
        memset(myblock, 1, MEGABYTE);
        sleep(1);
    }
    exit(0);
}

# malloc_test 파일을 malloc_test 실행 파일로 만듦
$ gcc -o malloc_test malloc_test.c
$ ls -al
-rwxr-xr-x  1 root root 8568 Oct 11 18:02 malloc_test
-rw-r--r--  1 root root  433 Oct 11 18:01 malloc_test.c

3. RES의 malloc 테스트 실행 결과

  • malloc()을 단독으로 요청하는 것이 아니라 할당 받은 메모리에 쓰기함 → RES 영역이 VIRT 영역 늘어나는 비율과 비슷하게 늘어남

  • 메모리 사용과 관련해서 VIRT 뿐만 아니라 실제 메모리를 쓰는 RES를 확인할 수 있음

  • top 명령으로 해당 프로세스의 변화 확인 → 시간이 지나면서 VIRT과 함께 RES가 계속해서 높아짐

    # 위에서 생성한 malloc_test 실행파일 실행
    $ ./malloc_test
    Currently allocating 1 MB
    Currently allocating 2 MB
    Currently allocating 3 MB
    Currently allocating 4 MB
    Currently allocating 5 MB
    # [...생략...]
    
    # 다른 터미널로 해당 내용 확인
    $ top -b -n 1 | grep -i malloc
    66652 root      20   0   21692  17772    400 S   0.0  0.0   0:00.01 malloc_test
    
    $ top -b -n 1 | grep -i malloc
    66652 root      20   0   35056  31236    400 S   0.0  0.0   0:00.04 malloc_test
    
    $ top -b -n 1 | grep -i malloc
    66652 root      20   0   45336  41532    400 S   0.0  0.0   0:00.05 malloc_test
    
    $ top -b -n 1 | grep -i malloc
    66652 root      20   0   57672  53940    400 S   0.0  0.0   0:00.07 malloc_test
    
    $ top -b -n 1 | grep -i malloc
    66652 root      20   0   62812  58956    400 S   0.0  0.0   0:00.08 malloc_test

※ Page Faults

  • 프로그램이 자신의 주소 공간에는 존재하지만 시스템의 RAM에는 현재 없는 데이터나 코드에 접근 시도하였을 경우 발생하는 현상
  • Page Faults 발생하면 운영 체제는 데이터를 메모리로 가져와서 Page Faults가 전혀 발생하지 않은 것처럼 프로그램이 계속적으로 작동하게 해줌

※ Page Table

  • 가상 주소와 물리 메모리 주소의 매핑 테이블
  • 프로세스마다 하나씩 존재하게 되며, 메인 메모리 (RAM)에 상주
  • 많은 프로세스가 구동될 수록, 페이지 테이블로 인한 메인 메모리 사용이 커짐을 의미


SHR → 다른 프로세스와 공유하고 있는 shared memory의 양을 의미

  • SHR는 공유하고 있는 메모리 크기
  • SHR 영역에 대표적으로 등록되는 내용은 라이브러리(library) → 대부분의 리눅스 프로세스는 glibc라는 라이브러리를 참고하기에 해당 라이브러리를 공유 메모리에 올려서 사용
  • 공유메모리에 올려놓고 사용하지 않고, 사용하는 프로세스마다 glibc의 내용을 메모리에 올려서 사용하는 것은 공간 낭비
  • 커널은 공유메모리라는 개념을 도입했고, 다수의 프로세스가 함께 사용하는 라이브러리는 공유메모리 영역에 올려서 함께 사용하도록 구현
  • VIRT는 실제는 할당되지 않는 가상공간이기 때문에 해당 값이 크다고 해도 문제가 되지 않음
  • 실제 사용하고 있는 메모리는 RES 영역이기 때문에 메모리 점유율이 높은 프로세스를 찾기 위해서는 RES 영역이 높은 프로세스를 찾아야함
  • 매핑된 라이브러리 전체는 VIRT와 SHR에 포함되어도, 실제 사용 중인 함수가 있는 일부 메모리만 RES에 포함
  • 커널은 메모리 낭비를 막기위해 공유 메모리라는 개념을 도입했고, 다수의 프로세스가 함께 사용하는 라이브러리는 공유 메모리 영역에 올려서 함께 사용하도록 구현

+ Recent posts