CSAPP › 가상메모리 단원의 추가 알게 된 점(Week6_Day4)
오늘은 이번주 공부했던 내용들의 흐름이 어느정도 이해가 되어서 정리 해보려한다. + 어제 부족했던 내용 보완 및 수정.
가상메모리
가상메모리는 각 프로세스가 실행이 될 때 일정 크기를 커널로 부터 할당 받는다. 32비트 환경에서는 4GB(2^32) 64비트 환경에서는 2^48 또는 2^57이라고 한다.
32비트에서는 2^32바이트인 4GB를 다 쓰면서 왜 64비트 환경에서는 2^48바이트 또는 2^57바이트로 사용 될까?
찾아본 결과 32비트와 64비트의 운영체제와 하드웨어의 설계의 차이 때문이라고 하는데, 64비트는 운영체제에서 효율과 관리 측면에서 사용가능한 가상 메모리를 제한한다고 한다. 신뢰도 있는 출처에서 찾은 정보는 없기 때문에 정확한 이유는 나중에 시간있을때 꼼꼼히 찾아봐야 할 것 같다.
가상메모리와 페이징
앞서 가상메모리와 물리메모리는 같은크기(보통 4KB)로(페이지, 프레임) 나누고 1대1 매핑이 된다고 했다.
이 용어 때문에 혼동이 있었는데 가상메모리가 물리 메모리와 같은 크기로 매칭이 된다는 얘기가 아니다.
단시 하나의 가상주소에 하나의 물리주소가 매핑이 된다는 이야기일 뿐이다(하나의 물리 주소를 두개의 가상주소가 가리킬 수 없다는 뜻도 아님!).
힙
힙은 가상메모리의 일부이다.
프로세스가 처음에 할당 받은 가상메모리에는 코드영역, 데이터 영역, 힙, 스택 등이 존재하고, 힙은 그 중에서 동적으로 할당이 가능한 영역인 것이다.
요구 페이징
리눅스의 커널이 Lazy하게 작동하며 실제로 cpu에서 물리주소의 데이터에 접근 하려 할때까지 프로그램이 요청하더라도 물리주소를 주지 않고 가상주소의 엔트리만 페이지테이블에 등록하는 행위 이다.
Demand zero memory
해당 영역은 요구 페이징의 결과로 생기는 영역이다. 프로세스가 요청한 하지만 물리 메모리는 할당되지 않는 가상 메모리의 영역을 일컫는 용어이다.
동적메모리 할당
정적으로 할당 할 경우 컴파일시 스택에 메모리를 할당하며, 프로그램 종료시 까지 할당 된 상태를 유지한다. 동적 할당의 경우 런타임시에 힙에 할당을 하거나 해제하며, 그 이유는 프로그램을 실행시키키 전에 자료구조의 크기를 알 수 없는 경우가 많기 때문이다.
동적 메모리 할당기(Dynamic Memory Allocater)
동적 메모리 할당기는 프로세스의 가상메모리 영역 중 힙 영역을 탐색하며 가용블록을 찾아 할당하거나 해제, 없을 경우 힙 영역을 위로 확장시켜서 새로운 영역을 할당 해 준다.
힙 영역의 확장 : sbrk라는 system call을 통해서 시스템으로 부터 메모리를 할당받고 이의 포인터를 반환하는 것.
할당기의 종류
명시적 할당기 :
할당 된 블럭을 명시적으로 할당하고 해제 해주는 행위(malloc, free).묵시적 할당기 :
java, python의 GC처럼 할당 된 블록이 더 이상 사용되지 않으면 감지해서 할당 해제해주는 할당기(물론 C에는 없다).
전체 흐름
프로세스는 실행 되면서 커널에게 가상메모리를 할당을 받는다.
실행 중 동적 메모리 할당이 필요할 때 커널에게 메모리 할당을 요구한다.
커널은 너가 필요한건 알겠는데, 지금 당장은 안쓸거잖아? 하고 힙에 프로세스가 요구한 만큼의 공간을 페이지 테이블에 엔트리만 등록한다.
그 결과 프로세스는 본인이 메모리를 할당을 받았다고 착각한다.
CPU가 실제로 데이터에 접근하기 위해 가상주소로 접근을 한다.
페이지 테이블을 살펴보았지만 vaild bit가 0일 것이다.
페이지 폴트가 발생하고 그제서야 물리 주소를 매핑 시켜준다.
정상적으로 프로그램이 작동한다.
페이지 폴트가 발생하는 경우에는 2가지가 있는데, 접근하고자 하는 정보가 물리 메모리에 로드 된 적이 없어 저장 공간에 있는 경우와 스왑아웃 되어 스왑공간에 있는 경우이다.
저장공간에 있는 경우 보통 디스크는 블록 단위로 나누어져 있고 이 또한 4kb인 경우가 대다수 이기 때문에 해당 데이터의 필요한 공간 만큼 물리 메모리의 프레임에 올리게 된다. 스왑 공간에 있는 경우는 페이지 테이블에 스왑공간에서의 위치 정보가 기록되어 있기 때문에 해당 데이터를 물리 메모리로 올리게 된다. 이후 페이지 테이블을 업데이트하여 정상적으로 데이터에 접근 할 수 있게 된다.