메모리 = 2개의 파트로 나눠짐.
- 높은 메모리 주소 = 운영체제
- 낮은 메모리 주소 = App.
- 대부분 이러한 형식을 따른다.
여기에선 사용자 프로세스가 어떻게 할당되는지를 봄.
- 각 사용자 프로세스는 다음 프로세스가 적재된 영역과 인접한 하나의 메모리 영역에 적재됨.
- 이 때 어떻게 프로세스가 메모리에 접근할지, 또 할당할지를 보자.
메모리 보호
프로세스가 자신이 소유하지 못한 메모리를 접근할 수 없게 만드는 방법.
이미지에서와 같이 상한 레지스터와 재배치 레지스터를 이용한다.
- 상한 레지스터 : 논리 주소의 범위를 저장.
- 재배치 레지스터 : 가장 작은 물리 주소 저장.
CPU 스케줄러가 다음으로 수행할 프로세스를 선택할 때, 디스패처는 문맥 교환의 일환으로 재배치 레지스터와 상한 레지스터에 정확한 값을 적재한다.
CPU에 의해 생성되는 모든 주소는 이 레지스터의 값을 참조.
따라서, 프로그램끼리의 충돌을 방지할 수 있다.
재배치 레지스터의 이점
- 운영체제의 크기를 맘대로 조절할 수 있다.
- ex. 필요할 때만 장치 드라이버의 코드를 적재할 수 있다.
메모리 할당
가변 파티션
프로세스를 메모리의 가변 크기 파티션에 할당.
-
처음에는 프로세스 5, 8, 2가 적재
-
프로세스 8 종료 후 하나의 hole이 생김.
hole = 사용 가능한 공간
-
프로세스 9가 도착 후 할당
-
프로세스 5 종료
-
서로 떨어져 있는 2개의 hole이 생김.
프로세스와 할당
프로세스가 시스템에 들어오면, OS는 프로세스의 요구 사항과 현재 메모리를 고려해 공간을 할당.
- 프로세스가 메모리를 할당받으면, 이후로는 CPU 할당을 위해 경쟁.
메모리가 충분하지 않은 경우 2가지 옵션이 있음.
- 거부하고 메세지를 보낸다.
- 대기 큐에 넣는다.
hole 관리
프로세스가 공간을 달라고 할 때, 적절한 hole을 주는 것이 필요하다.
ex. hole > 프로세스의 요구면, hole을 둘로 잘라 하나는 주고 다른 하나는 남겨둠.
이를 동적 메모리 할당 문제라고 함.
이 문제의 해결법은 크게 3가지가 존재.
- 최초 적합 : 1번째 사용 가능한 hole을 할당. 검색은 시작점이나 지난번 검색이 끝났던 곳에서 새로 시작할 수 있다. 충분히 큰 가용공간을 찾았을 때 검색을 끝낼 수 있다.
- 최적 적합 : hole 중 가장 작은 것을 택한다. 리스트가 크기 순으로 놓여있지 않으면, 쭉 검색해야 한다.
- 최악 적합 : hole 중 가장 큰 것을 택한다. 주고 남은 것은 다른 프로세스를 위해 쓸 수 있다. 리스트가 크기 순으로 놓여있지 않으면, 쭉 검색해야 한다.
최초 적합이나 최적 적합이 최악 적합보다는 시간, 메모리 이용 측면에서 좋다.
속도는 최초 적합 < 최적 적합 < 최악 적합 순이라고 생각하면 될 듯.
단편화
외부 단편화
만약 프로세스가 다음과 같이 된다면?
유휴 공간들이 너무 작은 조각들로 분산된 상태. 합치면 충분한 hole이 나온다.
이를 외부 단편화(external fragmentation)라고 한다.
단편화의 크기에 따라 최초 적합 / 최적 적합의 선택 여부가 갈린다.
또, 메모리의 전체 크기와 프로세스 크기들도 외부 단편화에 따라 큰 영향을 미칠 수 있다.
- 최초 적합의 경우, N개의 블록이 할당되었을 때 0.5N개의 블록이 단편화 때문에 손실됨.
- 이를 50% 규칙이라고 명명함.
내부 단편화
이러한 외부 단편화를 해결하려고 처음부터 메모리를 쪼개서 분배하는 방식을 고안하기도 한다. 그러나 이 방식은 다음과 같은 단점이 있다.
처음부터 모든 메모리를 2바이트 단위로 쪼개고, 이를 1개의 공간이라고 생각해보자. 만약 어느 한 프로세스가 18001바이트를 요구했다면, 운영체제는 9001개의 공간을 줘야 할 것이다.
이때, 무조건 1바이트가 남게 된다.
이와 같은 현상을 내부 단편화라고 한다.
압축
또 다른 외부 단편화 해결법으로, 모든 가용공간을 한쪽으로 몰아버린다.
그러나 항상 압축이 가능한 것은 아니다.
- 재배치가 적재 시간에 동적으로 이뤄지는 경우
- 압축을 하는데 비용이 적당한 경우
그래서 나오는 전략이 페이징이다.
⇒ 한 프로세스의 논리 주소 공간을 여러 개의 비연속적인 공간으로 나눈다.
⇒ 메모리를 쓸 수 있을 때 프로세스를 할당한다.