❗️강의 운영체제 (반효경) 공부 내용을 정리한 글 입니다.
[ 그림 1 ] 에서 디스크 내 프로그램 실행 파일은 메인 메모리 (= 물리적 메모리, RAM)에 로드 되기 전 가상 메모리(= 논리적 메모리)를 갖고 있고 이 가상 메모리를 기반으로 (화살표 방향, ←) 메인 메모리에 매핑되는 것을 볼 수 있다.
[ 그림 1 ] 에서 실행 파일은 소스 코드를 기반으로 만들어지는데 여기서는 컴파일 언어를 기반으로 설명한다. 컴파일 단계를 거치면 [ 그림 2 ] 와 같이 연산 코드, 데이터 등에 가상 메모리 주소가 할당되어 있는 것을 볼 수 있다. 각 프로세스 별로 0번지 부터 시작하는 특징이 있다. 모든 프로세스가 0번지 부터 시작하면 충돌될 수 밖에 없지만 말 그대로 논리적, 가상 메모리 공간이므로 충돌 개념이 적용되지 않는다.
[ 그림 1 ] 에서 메모리 ◀︎ 가상 메모리
과정은 결국 각 프로세스 별로 독립적으로 갖고 있는 가상 메모리를 물리 메모리 공간에 할당하는 것으로 이를 주소 바인딩 (address binding) 라고 한다.
주소 바인딩에는 세 가지 종류가 있다. 이 종류는 주소 바인딩 작업이 어떤 시점에 작동 하는지에 따라 다르다고 할 수 있다.
- 컴파일 타임 바인딩 :
개발자는 개발 과정에서 실제 물리 메모리 공간을 고려하면서 작업하지 않고 메소드 이름, 변수 이름 등을 통해 메모리 공간에 읽기 / 쓰기를 한다. 이 과정에서 사용되는 메모리 주소를 Symbolic Address 라고 한다. 이후 해당 소스 코드가 컴파일 되면 앞서 [ 그림 2 ] 에서 봤듯이 논리적 주소로 변환된다.
컴파일 타임 바인딩에서는 컴파일 과정에서 생성된 논리적 주소를 그대로 물리 메모리 공간에 할당하는데, 컴파일 단계에서 이미 논리적 주소를 어떤 물리 메모리 공간에 할당할 지 알 수 있다는 전제를 갖고 있기 때문이다. 컴파일 단계에서 이미 주소값이 고정된다는 점에서 절대 코드를 생성한다고 표현하기도 한다.
- 로드 타임 바인딩 :
컴파일 타임 바인딩과 달리 컴파일 시점에 어떤 물리 메모리 공간에 할당해야 하는지 알지 못하기 때문에 컴파일 과정에서 생성된 코드는 주소 공간을 재배치할 수 있는 재배치 가능 코드가 생성돼야 한다. 재배치 가능 코드에는 논리적 주소가 있고, [ 그림 3 ]과 같이 로드 타임 바인디에서는 해당 프로그램(실행 파일)이 실행되는 시점에 물리 메모리 공간 할당이 시작된다.
- 런타임 바인딩 :
이름 그대로 프로세스 수행이 시작된 이후에도 프로세스의 물리 메모리 위치를 옮길 수 있는 바인딩 방식으로 하드웨어 지원(MMU을 통해 구현할 수 있다.
앞서 런타임 바인딩에서 언급한 하드웨어가 MMU다. MMU는 주소 바인딩 역할을 수행한다. 다시 말해 논리적 주소를 물리적 주소로 매핑 해주는 역할을 한다.
[ 그림 4 ] 에서 CPU가 논리적 주소를 요청하면 MMU가 해당 논리적 주소에 매핑되어 있는 물리적 주소를 계산해서 반환해준다. 이 때 이러한 과정이 진행되기 위해서는 한 프로세스 단위로 해당 프로세스가 물리 메모리 공간의 시작 위치를 알고 있어야 한다. 이 정보를 relocation register
라고 한다.
CPU가 논리적 주소 346을 요청하면, MMU는 relocation register(14000) + 346 = 14346 위치를 반환하는데 이 위치가 논리적 주소가 매핑된 물리적 주소다. 만약 CPU가 프로세스에 할당된 물리 메모리 공간이 아닌 곳을 요청하면 어떻게될까? 각 프로세스 별로 독립적으로 갖고 있는 메모리 공간이 있고, 프로세스는 이 공간이 아닌 곳에 요청을 하게 되면 트랩 (인터럽트 일종)이 발생하여 해당 프로세스가 운영체제에 의해 종료된다.
이 때 해당 프로세스의 사이즈를 결정하는 것이 limit register
다. [ 그림 4 ] 와 같이 relocation register (14000), limit register (3000) 인 경우, 14000 ~ 17000 가 해당 프로세스에 할당된 물리 메모리 공간이라고 할 수 있다. [ 그림 5 ] 와 같이 CPU가 limit register 값 보다 큰 논리적 주소 공간을 요청하게 되면 트랩이 발생한다.