7장 메모리 관리
서론
컴퓨터에는 32비트, 64비트의 주소체계가 있다.
32비트라면 2^32
가지의 서로 다른 메모리 위치를 구분할 수 있고, 64비트면 2^64
만큼 가능하다.
컴퓨터에서는 byte 단위로 메모리 주소를 부여하기 때문에 32비트는 2^32
바이트, 64비트는 2^64
바이트만큼의 메모리 공간에 서로 다른 주소를 할당할 수 있다.
물론 32비트 그대로 사용하지 않고 효율적으로 사용하기 위해 페이지 단위로 구분한다.
보통 4KB(2^12
byte)로 구분하며, 페이지 하나의 크기가 2^12
바이트이므로 페이지 내에서 바이트별 위치 구분을 위해서는 12비트가 필요하다.
- 따라서 총 32비트에서 하위 12비트는 페이지 내에서의 주소를 나타내게 되는 것이다.
- 드림핵에서 보면 이 내용이 있는데, 이제 이해가 가는 부분..
- dreamhack.io/forum/qna/1484
주소 바인딩
두 가지 주소가 있는데, 논리적(가상) 주소와 물리적 주소가 있다.
프로그램 실행 시 메모리에 적재되면 프로그램마다 주소 공간이 생기는데, 이를 논리적 주소라 한다.
프로그램이 물리적 메모리에 실제로 올라가는 위치를 물리적 주소라고 한다.
주소 바인딩은 프로그램의 논리적 주소를 물리적 메모리 주소로 매핑하는 작업이다. (논리적 주소 -> 물리적 주소)
주소 바인딩은 프로그램의 물리적 메모리가 적재되는 시기에 따라 3가지 방법이 있다.
- 컴파일 타임 바인딩 (compile time binding)
- 컴파일 시 프로그램의 물리적 메모리 주소가 결정된다.
- 단점은 물리적 메모리 주소를 변경하고자 하면 컴파일을 다시 해줘야 한다.
- 비현실적이며 시분할 시스템에서 잘 사용하지 않는다.
- 로드 타임 바인딩 (load time binding)
- 프로그램 실행 시 물리적 메모리 주소가 결정된다.
- 로더(loader)의 책임하에 물리적 메모리 주소가 부여되며 종료될 때까지 위치가 고정된다.
- 로더란 사용자 프로그램을 메모리에 적재시키는 프로그램이다.
- 컴파일러가 재배치 가능 코드(relocated code)를 생성한 경우에 가능한 방법이다.
- 실행시간 바인딩 (run time binding, execution time binding)
- 프로그램이 실행한 이후에도 물리적 메모리 주소가 변경될 수 있다.
- CPU가 주소를 참조할 때마다 주소 매핑 테이블을 이용해 바인딩을 점검해야 한다.
- 이 방식이 가능하려면 base register와 limit register를 포함해 MMU(Memory Management Unit)라는 하드웨어적인 지원이 필요하다.
- MMU는 논리적 주소를 물리적 주소로 매핑하는 하드웨어 장치다.
MMU 기법은 CPU가 프로그램의 논리적 주소를 base register의 값을 더해 물리적 메모리 주소로 참조하는 방식이다.
base register는 프로그램의 물리적 메모리 시작 주소를 가지고 있다.
따라서 base register를 재배치 레지스터 (relocation register)라고도 하며, MMU 기법에서는 문맥교환으로 수행 중인 프로세스가 바뀌면 base register의 값을 그 프로세스에 해당되는 값으로 재설정한다.
또한 다중 프로그래밍 환경에서 메모리 보안이 이루어지지 않아 다른 프로세스의 주소를 침범하는 경우를 방지하기 위해 limit register를 사용한다.
limit register는 CPU가 메모리 참조 요청 시 그 주소를 자신의 값과 비교해 큰지를 먼저 체크하여 메모리 보안을 유지한다.
메모리 관리 용어
- 동적로딩
- 프로세스의 주소 공간 전체를 메모리에 적재하는 것이 아닌, 해당 부분이 불릴 때 그 부분만 메모리에 적재하는 방식
- 동적로딩은 운영체제의 특별한 도움없이 프로그램 자체에서 구현 가능하고 운영체제가 라이브러리를 통해 지원할 수도 있다.
- 동적연결
- 연결(linking)은 컴파일 후 object file과 library 파일을 합쳐 실행파일로 만드는 과정
- 정적연결이란 사용자 코드와 라이브러리 코드가 합쳐저 실행파일을 생성하는 방식으로, 실행파일이 크며 동일 라이브러리를 여러 프로세스에서도 적재하므로 낭비된다.
- 동적연결이란 라이브러리가 실행 시점에 연결되는 것으로, 실행 파일에 라이브러리 코드가 없으며 실행파일의 라이브러리 호출 부분에 stub이란 작은 코드를 둔다.
- stub을 통해 메모리에 해당 라이브러리가 적재되어있는지 확인하여 그럴 경우 참조하고, 아닐 경우 메모리에 적재한 후 호출한다.
- 여러 프로그램이 공통으로 사용하는 라이브러리를 메모리에 한 번만 적재하므로 효율적이다.
- 운영체제의 지원을 필요로 한다.
- 중첩 (overlays)
- 프로세스의 주소 공간을 분할해 실제 필요한 부분만 메모리에 적재하는 기법
- 초창기 컴퓨터는 메모리 공간이 작으므로 분할해서 올려야 했다.
- 동적로딩과 개념은 상이하나 목적은 다르다.
- 직접 구현해아 하는 방식으로 복잡한 작업이다.
- 스와핑 (swapping)
- 프로세스의 주소 공간을 일시적으로 스왑 영역으로 내려놓는 것을 말한다.
- 스왑 영역을 백킹스토어(backing store)라고도 부르며, 디스크 내에 파일 시스템과는 별도로 존재하는 일정 영역이다.
- 휘발성이고 많은 프로세스를 담을 수 있을만큼 커야 하며, 접근 속도도 빨라야 한다.
물리적 메모리의 할당 방식
물리적 메모리 공간은 낮은 주소에 운영체제의 코드가 있는 운영체제 상주 영역과 사용자 프로세스 영역으로 나눈다.
사용자 프로세스 영역은 메모리를 올리는 방식으로 아래와 같다.
- 연속할당 방식
- 각각의 프로세스를 메모리의 연속적인 공간에 올리는 방식
- 물리적 메모리를 다수의 분할로 나누어 하나의 분할에 하나의 프로세스가 적대되도록 한다.
- 분할 방식에 따라 고정분할과 가변분할로 나눈다. (챕터 2 확인)
- 고정분할 방식은 물리적 메모리를 고정된 크기의 분할로 미리 나누는 방식
- 가변분할 방식은 프로그램이 실행되고 종료되는 순서에 따라 분할을 관리하는 방식
- 불연속할당 방식
- 하나의 프로세스를 물리적 메모리의 여러 영역에 분산해 적재하는 방식
- 페이징 기법 (paging)
- 프로세스의 주소 공간을 동일한 크기의 페이지 단위로 나누어 물리적 메모리의 서로 다른 위치에 저장하는 방식
- 물리적 메모리 공간을 미리 페이지 단위로 나누어둔다.
- 세그멘테이션 기법 (segmentation)
- 코드, 스택, 데이터 등 세그먼트로 나누어 세그먼트 단위로 적재하는 방식
- 페이지드 세그먼테이션 (paged segmentation)
- 세그먼트 하나를 다수의 페이지로 구성하는 방식
페이징 기법
페이징 기법은 프로세스의 주소 공간을 동일한 크기의 페이지 단위로 나누어 물리적 메모리의 서로 다른 위치에 저장하는 방식이다.
예를 들면, 일부는 스왑영역에, 일부는 물리적 메모리에 혼재시키는 것이 가능하다.
페이징 기법에서는 물리적 메모리 공간을 미리 페이지 단위로 나누어둔다.
따라서 연속할당과는 달리 동적 메모리할당 문제가 없으나, 주소 변환 절차가 복잡하다.
특정 프로세스의 몇 번째 페이지가 물리적 메모리의 몇 번째 프레임에 있는지 알아야하므로 페이지별 주소 변환 정보를 유지해야 한다.
따라서 주소 변환을 위한 페이지 테이블을 가지며, 이 테이블은 프로세스가 가질 수 있는 페이지 개수만큼 주소 변환 엔트리를 가지고 있게 된다.
세그먼테이션
필요하면 정리
페이지드 세그먼테이션
필요하면 정리