OS 캐시
- OS에는 디스크 내의 데이터에 빠르게 액세스할 수 있도록 하는 구조가 갖춰져 있다.
- OS는 메모리를 이용해서 디스크 액세스를 줄인다.
- 애플리케이션에서 이를 활용한다면 OS에 상당부분을 맡길 수 있다.
- 이를 가능하게 하는 것이 OS캐시이다.
- 리눅스의 경우에는 페이지 캐시(page cache), 버퍼 캐시(buffer cache)라고 하는 캐시 구조를 갖추고 있다.
가상 메모리
프로그램이 메모리를 사용할 때 물리적인 메모리를 직접 다루지 않고, 추상화한 소프웨어적인 메모리를 다루는 구조이다.
하드웨어에서 제공하는페이징(paging)
이라고 하는 가상 메모리 구조를 사용해 실현한다.
- 즉, 가상 메모리란 OS가 커널 내에서 물리 메모리를 추상화 한 것이다.
- 프로세스에서 메모리를 다루기 쉽게 하는 이점을 제공한다.
- 가상 메모리의 관리는 OS가 담당한다.
※ 참고. 스왑(Swap)
- 스왑은 가상 메모리를 응용한 기술 중 하나이다.
- 물리 메모리가 부족할 때 2차 기억창치(주로 디스크)를 메모리로 간주해서 외형상의 메모리 부족을 해소한다.
- 물리 메모리가 부족한 경우 장시간 사용되지 않은 영역의 가상 메모리와 물리 메모리 영역 매핑을 해제한다.
- 해제된 데이터는 디스크 등에 저장해두고 다시 필요해지면 원래로 되돌린다.
프로세스에서 메모리에 접근하려면 ?
- 프로세스에서 OS로 메모리를 요청한다.
- OS가 메모리에서 비어있는 (물리)메모리 주소 찾는다.
- OS는 프로세스로 (가상)메모리 주소를 반환한다.
- OS는 메모리 4KB 정도를 블록으로 확보해서 관리한다.
- 하나의 블록 단위를 ‘페이지’라고 한다.
- 즉, 페이지란 OS가 물리 메모리를 확보/관리하는 단위이다.
- OS는 프로세스에서 메모리 요청을 받으면 필요한 만큼의 페이지를 확보해서 프로세스에 반환한다.
- OS는 메모리 4KB 정도를 블록으로 확보해서 관리한다.
- 프로세스는 가상 메모리에 접근한다. (물리 메모리로 직접 접근할 수 없음)
- 커널이 프로세스에 반환하는 가상 메모리 영역은 아직 실제로 물리 메모리와 연결되어 있지 않다.
- 즉, 실체가 없는 메모리 영역이다.
- 프로세스가 가상 영역에 대해 쓰기 작업을 수행하는 시점에 물리 메모리 영역과 연결관계를 맺는다.
가상 메모리를 사용해야 하는 이유
가상 메모리를 통해 얻을 수 있는 이점은 매우 크며, 이는 멀티 태스킹 OS를 지탱하는 중요한 역할을 담당한다.
- 물리 메모리로 탑재되어 있는 용량 이상의 메모리를 다룰 수 있을 것처럼 프로세스에게 보일 수 있다.
- 물리 메모리상에서는 흩어져 있는 영역을 연속된 하나의 메모리 영역으로 프로세스에게 보일 수 있다.
- Swap을 사용할 수 있다.
- 서로 다른 두 개의 프로세스가 참조하는 가상 메모리 영역을 동일한 물리 메모리 영역에 대응 시킬 수 있다.
- 이를 통해 두 개의 프로세스가 메모리 내용을 공유할 수 있다.
IPC(Inter Process Communication)
공유 메모리 등은 이 방법으로 구현된다.
리눅스의 페이지 캐시 원리
OS는 확보한 페이지를 메모리상에 계속 확보해두는 기능을 갖고 있다. 이를 ‘페이지 캐시’라고 한다.
즉, 커널이 한 번 할당한 메모리를 해제하지 않고 계속 남겨두는 것이 페이지 캐시의 기본이다.
페이지 캐싱 과정
- OS는 프로세스에게 요청받은 데이터를 디스크로부터 블록의 크기(ex : 4KB)만큼 읽는다.
- 읽은 데이터를 (물리)메모리상에 위치시킨다.
- 물리 메모리 주소를 가상 메모리 주소로 변환하여 프로세스에게 알려준다.
- 프로세스는 (가상)메모리에 접근해서 데이터를 읽는다.
- 프로세스가 데이터를 읽고 나서도 OS에서는 해당 데이터를 메모리에서 해제하지 않고 남겨둔다.
- 이를 통해 다른 프로세스에서 동일한 데이터가 필요한 경우 OS가 다시 디스크에 접근하지 않아도 된다.
※ 캐시 이외의 메모리가 필요하게 되면 오래된 캐시가 파기된다.
즉, 메모리가 1GB 인데 그 중 900MB가 캐시로 사용되고 있다고 해서 메모리가 부족하다고 생각하지 않아도 된다.
4GB의 파일을 1.5GB의 여유가 있는 메모리에 캐싱할 수 있을까?
정답은 ‘가능하다’이다. 어떻게 가능한 것인지 원리를 살펴보자.
- 캐싱하고자 하는 파일에 대해
i노드 번호
와오프셋
두 가지 값을 키로 캐싱한다.- i노드 번호 - 리눅스가 파일을 식별하는 번호
- 오프셋 - 파일의 어느 위치부터 시작할지를 나타내는 값
- 따라서, 파일 전체가 아닌 일부를 캐싱할 수 있다.
- ‘파일의 크기 > 메모리 공간’ 이기 때문에, 파일의 일부를 캐싱하더라도 결국 메모리 공간이 꽉 차게 된다.
LRU(Least Recently Used)
- 새로운 데이터를 캐싱하기 위한 메모리 공간을 확보하기 위해 가장 오래된 데이터를 파기
- 파일이 아무리 크더라도 캐싱된 키로부터 해당 페이지를 찾을 때의 데이터 구조는 최적화 되어있다.
- OS(커널) 내부에서 사용되고 있는 자료 구조는
Radix Tree
이다. - 캐싱된 파일이 커지더라도 캐시 탐색속도가 떨어지지 않도록 개발된 자료 구조이다.
- OS(커널) 내부에서 사용되고 있는 자료 구조는
참고 자료
- 이토 나오야 외 1명, 『웹 개발자를 위한 대규모 서비스를 지탱하는 기술』, 제이펍(2011), 8장
- 이토 나오야 외 5명, 『24시간 365일 서버/인프라를 지탱하는 기술』, 제이펍(2009), 4장