- 프로세스에서 중요한 요소 → 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에 포함
- 커널은 메모리 낭비를 막기위해 공유 메모리라는 개념을 도입했고, 다수의 프로세스가 함께 사용하는 라이브러리는 공유 메모리 영역에 올려서 함께 사용하도록 구현
'OS(운영체제) > 리눅스(Linux)' 카테고리의 다른 글
Linux 접속 로그 → btmp, wtmp, utmp, lastlog (0) | 2022.07.18 |
---|---|
[cache] Write Through와 Write Back 비교 (0) | 2022.07.18 |
OOM Scoring(Out Of Memory Scoring)이란 (0) | 2022.07.17 |
Network Ring Buffer Size 설정하기 (0) | 2022.07.15 |
CentOS iso 파일의 특정 버전과 Centos 버전의 EOL(End Of Life) (0) | 2022.07.03 |