프로그램이 프로세스가 되어 프로세서에 적재되기 위해서는 메모리에 적재되어야 실행이 가능하다.
💡메모리 = 중요한 작업 공간 -> 한정된 메모리를 다중 프로그래밍 환경에서 이용하기 위해서는 여러 프로세스가 함께 메모리를 사용하므로 효율적으로 관리해야한다.
메모리 관리를 위해 메모리 관리자가 존재하며, 메모리 관리 장치(MMU, Memory Management Unit)과 OS 관리 모듈을 함께 진행한다.
메모리 관리 정책
논리적 주소 (=가상 주소)
메모리 셀, 스토리지 요소, 네트워크 호스트와 같은 요소가 실행 중인 응용 프로그램의 관점에서 상주하고 있는 것처럼 보이는 주소
프로세스마다 독립적으로 가지는 주소 공간 : 프로세스의 내부에서 사용하고, 각 프로세스마다 0부터 시작
물리적 주소
논리적 주소에 대응되는 실제 주소, 메모리칩이나 디스크 공간에서 만든다
프로세스가 실행되기 위해 실제로 메모리(RAM)에 올라가는 위치
비교의 근거 | 논리 주소 | 실제 주소 |
---|---|---|
기본 | CPU가 생성한 가상 주소 | 메모리 유닛 내의 위치 |
주소 공간 | 프로그램을 참조하여 CPU가 생성한 모든 논리주소 집합을 논리 주소 공간이라고 한다 | 해당 논리 주소에 매핑된 모든 실제 주소집합을 실제 주소라고 한다 |
사용자 입장 | 사용자는 프로그램의 논리 주소를 볼 수 있다 | 사용자는 프로그램의 실제 주소를 볼 수 없다 |
액세스 가능 여부 | 사용자는 논리 주소를 사용하여 실제 주소에 액세스 | 사용자는 실제 주소에 직접 액세스 할 수 없다 |
생성시기 | CPU에 의해 생성된다 | MMU에 의해 계산된다 |
🛠논리적 주소와 물리적 주소의 변환은 MMU에서 관리한다.
: CPU에서 논리적 주소를 받아 고정 분할, 동적 분할, 페이징, 세그멘테이션 ... 을 이용한 변환 방법을 사용하여 물리적 주소로 변환시킨다.
어떤 프로그램이 메모리의 어느 위치에(어떤 물리적 주소에) load 될지 결정하는 과정
이는 binding하는 시점에따라 분류된다.
프로세스의 물리적 주소가 컴파일 때 정해진다.
프로세스가 메모리의 어느 위치에 들어갈지 미리 알고있다면 컴파일러가 절대 주소, 즉 고정된 주소를 생성한다. 따라서 위치가 변경된다면 재컴파일 해주어야 한다.
컴파일 주소 할당은 프로세스 내부에서 사용하는 논리적 주소와 물리적 주소가 동일하다.
문제점?
주소가 고정되어있기 때문에 메모리 상의 빈 공간이 많이 발생할 수 있어 비효율적이고, 로드하려는 위치에 이미 다른 프로세스가 존재할 수 있다.
잘 쓰이지 않는다.
프로세스가 메모리의 어느 위치에 들어갈지 미리 알 수 없다면 컴파일러는 Relocatable code를 생성해야한다.
(Relocatable code : 메모리의 어느 위치에서나 수행될 수 있는 기계 언어 코드)
그리고 Loader가 프로세스를 메모리에 load하는 시점에 물리적 주소를 결정한다.
따라서 논리적 주소와 물리적 주소가 다르다.
단점?
프로세스 내에 메모리를 참조하는 명령어들이 많아서, 이들의 주소를 다 바꿔줘야하기 때문에 로딩할 때의 시간이 매우 커질 수 있다.
잘 쓰이지 않는다.
프로세스가 수행 시작된 이후에 프로세스가 실행될 때 메모리 주소를 바꾸는 방법이다.
Runtime때 물리적 주소가 결정되며, 실행 도중 주소가 바뀔 수 있다.
CPU가 주소를 참조할 때마다 address mapping table을 이용하여 binding을 점검한다.
MMU라는 하드웨어 장치를 사용하여 논리적 주소를 물리적 주소로 바꿔준다.
프로세스가 CPU에서 수행되면서 생성해내는 모든 주소값에 대해서 base register의 값을 더해주어 물리적 주소를 생성하는 방식이다.
(base register는 하나이며, 프로세스끼리 공유)
❗️주의해야할 점
커널 모드인 경우, MMU가 물리적 주소로 변환하지 않고, 논리적 주소를 그대로 사용한다.
따라서 커널모드인지 체크하는 과정도 포함되어 있다.
메모리는 크기가 크지않아, 프로세스를 임시로 디스크에 보냈다가 다시 메모리에 로드해야하는 상황이 발생한다.
swap out = 디스크로 내보내는 것
swap in = 메모리로 들여보내는 것
일반적으로 중기 스케줄러에 의해 swap out시킬 프로세스를 선정하며, 우선순위에 따라 어떤 프로세스를 swap in/out할지 결정한다.
우선순위가 낮은 프로세스를 swap out시키고, 높은 프로세스를 메모리에 올려 놓는다.
Compile Time , Load Time Binding = 원래 메모리 위치로 swap in 해야한다.
Executino Time Binding = 추후 빈 메모리 영역 아무곳에나 올릴 수 있다.
메모리는 일반적으로 커널 영역과 사용자 프로세스 영역으로 나누어서 사용된다.
사용자 프로세스 영역의 할당 방법으로는 Contiguous Allocation(연속적 할당), Noncontiguous Allocation(비연속적 할당)이 있다.
여기서 Contiguous Allocation(연속적 할당)을 알아보자.
이는 각 프로세스들이 연속적인 메모리 공간을 차지하는 것이다.
각 프로세스를 메모리에 담기위해 메모리는 미리 공간을 분할해 둔다.
고정 분할 (Fixed partition)
분할의 크기가 모두 동일하거나 혹은 서로 다를 수 있다. 분할 당 하나의 프로세스가 적재되기 때문에 동시에 메모리에 load되는 프로세스 수가 고정된다. 또 수행가능한 프로세스의 최대 크기가 제한된다.
가변 분할 (Variable partition)
프로세스의 크기를 고려해서 할당하기 때문에 분할의 크기나 개수가 동적으로 변한다.
이를 위해서는 기술적인 관리 기법이 필요하다.
단편화 = 프로세스들이 메모리에 적재되고 제거되는 일이 반복되면 프로세스들이 차지하는 메모리 틈 사이에 사용하지 못할만큼의 작은 공간들이 늘어나게 되는 현상
외부 단편화
총 공간을 계산했을 때 프로세스가 들어갈 수 있는 메모리가 있음에도 불구하고 공간들이 연속하지 않아 사용할 수 없는 경우를 말한다.
내부 단편화
프로세스가 사용하는 메모리 공간보다 분할된 공간이 더 커서 메모리가 남는 경우를 말한다.
예) 1000크기의 분할이 있고, 990크기의 프로세스가 들어갈 때, 10만큼의 공간이 남게되는데 이 현상을 내부 단편화라고 한다.
고정 분할 = 외부 단편화, 내부 단편화 모두 발생할 수 있다.
가변 분할 = 외부 단편화가 발생할 수 있다.
외부 단편화 해결방법