https://www.yes24.com/Product/Goods/122109062
그림으로 배우는 리눅스 구조 - 예스24
선배가 옆에서 하나하나 알려주듯 친절히 설명해주는실습과 그림으로 배우는 리눅스 지식의 모든 것 * Go 언어와 Python, Bash 스크립트 실습 코드 제공* 이 도서는 『실습과 그림으로 배우는 리눅
www.yes24.com
3장 '프로세스 스케쥴러'는 리눅스 특화라기보단 보편적인 OS 공부에 가까워서 한 번 읽어보고 포스팅하진 않았다. 혹시 스케줄링에 대해 궁금한 점이 있다면 OSTEP 운영체제 책이 오픈 소스로 제공되어 있으니 참고하길 바란다.
https://pages.cs.wisc.edu/~remzi/OSTEP/
Operating Systems: Three Easy Pieces
Blog: Why Textbooks Should Be Free Quick: Free Book Chapters - Hardcover - Softcover (Amazon) - Buy PDF - EU (Lulu) - Buy in India - Buy Stuff - Donate - For Teachers - Homework - Projects - News - Acknowledgements - Other Books Welcome to Operating System
pages.cs.wisc.edu
1. 메모리 필드 정보 파악
터미널에서 free 명령어를 입력하면 시스템에 설치된 메모리 용량과 사용 중인 메모리 용량을 바이트 단위로 파악할 수 있다.
각 필드를 설명하면 다음과 같다.
필드명 | 의미 |
total | 시스템에 설치된 전체 메모리 용량. 예제에서는 약 4GiB |
used | 시스템이 사용중인 메모리에서 buff/cache를 뺀 값 |
free | 명목상 비어 있는 메모리 |
shared | 여러 프로세스가 데이터를 공유할 수 있는 메모리 |
buff/cache | 버퍼, 캐시, 페이지 캐시가 이용하는 메모리. 시스템의 비어 있는 메모리(free 필드값)가 줄어들면 커널이 해제시킴. |
available | 실제로 사용 가능한 메모리. free 필드값과 비어 있는 메모리가 줄어 들었을 때 해제 가능한 커널 내부 메모리 영역 크기를 더한 값. |
표만 봐서는 이해하기 어려우므로, 그림으로 표현해 보자.
위와 같다! 이 중에서 used와 buff/cache에 대해서 살펴볼 것이다.
used
used는 프로세스와 커널이 사용하는 모든 메모리이다. OS를 배우면 알겠지만, 커널에도 각자의 스택, 프로세스, PCB 등을 가지고 있기 때문에 일정 공간이 필요하고, 우리는 이 부분을 건드릴 수 없다. 따라서 user process가 종료되었을 때 메모리가 해제되어 free가 늘어나는지를 다음 실습으로 확인해보자. 다음 memuse.py 코드를 실행해보자.
#!/usr/bin/python3
import subprocess
# 적당한 양의 데이터를 작성해서 메모리를 사용
# 메모리 용량이 작은 시스템이라면 메모리 부족으로 실패할 가능성이 있으므로
# size값을 줄여서 다시 실행
size = 10000000
print("메모리 사용 전의 전체 시스템 메모리 사용량을 표시합니다.")
subprocess.run("free")
array = [0]*size
print("메모리 사용 후의 전체 시스템 메모리 남은 용량을 표시합니다.")
subprocess.run("free")
1e8개 원소를 가진 list를 선언하고 난 후 메모리 용량을 보면, used 부분이 80MiB 정도 늘어났음을 확인할 수 있다. 동시에 free 파트도 80MiB가 줄었음을 확인할 수 있다. 한편 프로그램이 끝나면 메모리가 환수될 것이다. 실제로 돌려보면,
메모리가 원상태로 돌아왔음을 알 수 있다.
buff/cache
buff/cache는 8장에서 설명하는 페이지 캐시와 버퍼 캐시가 사용하는 메모리 용량을 의미한다. 이에 대해서 간단히 설명하면, memory hierarchy적인 접근법으로, 느린 저장 장치(hdd, ssd)의 파일 데이터를 접근 속도가 빠른 메모리를 캐시로 지정해서 일시적으로 저장 후 이걸 불러오는 기능을 한다. 그러면 cache에 데이터를 올리는 다음 .sh 코드를 통해 buff/cache 영역의 변화를 확인해보자.
#!/bin/bash
echo "파일 작성 전의 시스템 전체 메모리 사용량을 표시합니다."
free
echo "1GB 파일을 새로 작성합니다. 커널은 메모리에 1GB 페이지 캐시 영역을 사용합니다."
dd if=/dev/zero of=testfile bs=1M count=1K
echo "페이지 캐시 사용 후의 시스템 전체 메모리 사용량을 표시합니다."
free
echo "파일 삭제 후, 즉 페이지 캐시 삭제 후의 시스템 전체 메모리 사용량을 표시합니다."
rm testfile
free
buff/cache 부분이 1GiB 증가하고, 마찬가지로 free 부분에서 1GiB 감소함을 확인할 수 있다. 삭제후에는 cache가 삭제되므로, 원래대로 free 메모리가 돌아옴을 확인할 수 있다.
free 외에도 메모리 정보를 수집하는 방법으로 sar 명령어를 이용할 수 있다. 예를들어,
$ sar -r 1 5
의 경우에는 5초 동안 정보를 수집하는데, 1초 간격으로 수집 활동이 일어난다는 의미이다.
앞서 free 에서 buff/cache 을 한꺼번에 구했는데, sar 명령의 경우에는 kbbuffers 와 kbcached이 분리되어 표시되어 있으므로 유용하고, 시간에 따라 모든 메모리 정보를 한눈에 볼 수 있으므로 유용하다.
2. 메모리 재활용, 메모리 강제 해제
이번에는 user 프로세스가 증가하는게 아니라, 커널에서의 시스템 부하가 높아진다고 가정하자. 그렇다면 다음 순서로 메모리를 확보할 것이다.
- available 영역에서 "해제 가능" 한 부분을 free 영역으로 반납한다.
- kernel이 사용하도록 메모리를 부여한다.
- 나머지 원래 있던 free 영역의 메모리도 kernel에 부여한다.
이 과정을 거치면 다음 그림처럼 극단적인 경우 free 영역이 거의 없어지는 순간이 발생한다.
이 상태를 Out of Memory(OOM) state 라고 한다. 이렇게 되면 어떻게 해야 할까? 메모리 관리 시스템은 kernel과 user 중 어떤 프로세스가 더 중요할지 선택해야 할 순간이 온다. 답은 당연히, kernel이 더 중요하다! 따라서 OOM killer라는 기능을 통해 적당한 user 프로세스를 강제 종료시키고, 메모리를 free로 반납한다. 즉 다음과 같다.
실제로 OOM killer가 동작했을 때 dmesg 명령어로 커널 로그를 확인하면 다음과 같이 출력된다.
[XXX] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),...
이를 통해 OOM killer가 동작함을 확인하고, 이를 방지하기 위해 필요없는 user 프로세스를 미리 종료시키거나, 메모리를 더 할당해주는 대책이 필요하다.
그런데 메모리 용량이 충분한데도 OOM killer가 동작하는 경우가 있는데, 이는 메모리 누수(memory leak)가 발생한 경우이다. 이는 지금까지 논의했던 경우와 정반대로, user process의 메모리 사용량이 지나치게 증가하는 수상한 프로세스가 있을 때 발생한다. 이를 모니터링하기 위해서는 ps aux 같은 명령어의 RSS 필드를 보는 것이다. RSS 필드는 프로세스가 사용하는 메모리 용량을 의미하므로, 이런 프로세스를 발견한다면 원인을 찾고, 종료시키는 것이 대응 방안이다.
다음 포스트에서는 OS의 위대한 기능인 Virtualization 중 하나인 가상 메모리(Virtual Memory)에 대해 알아볼 것이다.
'Linux > 그림으로 배우는 리눅스 구조' 카테고리의 다른 글
[그림으로 배우는 리눅스 구조] 5. 프로세스 관리(응용편) (0) | 2024.08.29 |
---|---|
[그림으로 배우는 리눅스 구조] 4. 메모리 관리 시스템(2) (0) | 2024.08.29 |
[그림으로 배우는 리눅스 구조] 2. 프로세스 관리(기초편) (0) | 2024.08.27 |
[그림으로 배우는 리눅스 구조] 1. 리눅스 개요 (0) | 2024.08.27 |
[그림으로 배우는 리눅스 구조] 0. 환경 설정 (0) | 2024.08.27 |