메모리 관리

Tasker_Jang·6일 전
post-thumbnail

1. 논리 주소와 물리 주소

프로그램을 컴파일하면 주소가 0번지부터 시작합니다. 그런데 실제 메모리에는 다른 프로그램들도 올라가 있으므로 0번지에 놓일 리가 없습니다. 주소가 두 종류라는 뜻입니다.

  • 논리 주소(logical address): 프로세스마다 독립적으로 갖는 주소 공간. 모든 프로세스가 0번지부터 시작합니다. 가상 주소라고도 합니다
  • 물리 주소(physical address): 메모리에 실제로 올라가는 위치

CPU가 내보내는 주소는 항상 논리 주소입니다. 따라서 메모리에 닿기 전에 누군가 물리 주소로 바꿔 줘야 합니다.

2. 주소 바인딩

논리 주소를 물리 주소로 결정하는 일을 주소 바인딩(address binding)이라고 합니다. 언제 결정하느냐에 따라 셋으로 나뉩니다.

방식결정 시점생성되는 코드실행 중 이동
compile time binding컴파일할 때절대 코드 (absolute code)불가능
load time binding메모리에 올릴 때 (loader가 결정)재배치 가능 코드 (relocatable code)불가능
execution time binding실행 중에 매 접근마다재배치 가능 코드가능

compile time binding은 물리 주소가 컴파일 시점에 박히므로, 그 자리가 비어 있지 않으면 실행할 수 없습니다. 지금 쓰는 시스템은 모두 execution time binding입니다. 실행 도중에도 프로세스를 다른 위치로 옮길 수 있어야 하기 때문인데, 매 주소 접근마다 변환이 필요하므로 하드웨어 지원이 필수입니다.

3. MMU

그 하드웨어가 MMU(Memory Management Unit)입니다. 레지스터 두 개를 씁니다.

  • relocation register: 이 프로세스가 올라간 물리 메모리의 시작 주소
  • limit register: 이 프로세스가 쓸 수 있는 주소 공간의 크기

변환 규칙은 "논리 주소에 시작 주소를 더한다"입니다. 여기에 더해, 남의 영역을 침범하지 않는지 limit register로 검사합니다.

작은 예제

relocation register가 14000, limit register가 3000입니다.

  1. CPU가 논리 주소 346을 내보냅니다
  2. 346 < 3000이므로 범위 안입니다
  3. 346 + 14000 = 14346번지에 접근합니다
  4. 이번엔 CPU가 논리 주소 3500을 내보냅니다
  5. 3500 >= 3000이므로 자기 영역 밖입니다. MMU가 trap을 걸어 운영체제로 제어를 넘기고, 운영체제는 대개 그 프로세스를 강제 종료합니다

mode bit이 권한을 막았다면, limit register는 영역을 막습니다. 둘 다 소프트웨어가 아니라 하드웨어가 검사한다는 점이 같습니다.

4. 메모리를 아끼는 기법들

메모리는 늘 부족하므로 "안 쓰는 것은 안 올린다"는 아이디어가 여러 형태로 나옵니다.

기법내용비고
dynamic loading해당 루틴이 호출될 때 메모리에 올림오류 처리처럼 자주 안 쓰는 코드에 효과적
static linking라이브러리를 실행 파일에 포함시켜 둠파일이 커지고, 같은 라이브러리가 프로세스마다 중복
dynamic linking실행 시점에 라이브러리를 연결메모리에 한 벌만 두고 여러 프로세스가 공유
overlays필요한 부분만 올리되 프로그래머가 직접 관리메모리가 극히 작던 시절의 수작업 방식
swapping프로세스를 통째로 디스크 swap area로 내보냄내보내기가 swap out, 다시 올리기가 swap in

swapping에서는 주소 바인딩 방식이 바로 문제가 됩니다. compile time이나 load time binding이면 swap in할 때 원래 있던 자리로만 돌아갈 수 있습니다. execution time binding이면 아무 빈 자리에나 올리면 됩니다.

5. 연속 할당과 분할 방식

메모리는 크게 운영체제 상주 영역과 사용자 프로세스 영역으로 나뉩니다. 사용자 영역을 어떻게 나눠 주느냐에서 갈립니다.

  • 연속 할당(contiguous allocation): 프로세스를 메모리의 연속된 한 덩어리에 올립니다
  • 불연속 할당(noncontiguous allocation): 프로세스를 여러 조각으로 나눠 흩어진 위치에 올립니다

연속 할당은 다시 둘로 나뉩니다.

구분고정분할 (fixed partition)가변분할 (variable partition)
방식미리 정해진 크기로 영역을 나눠 둠프로세스 크기에 맞춰 그때그때 할당
동시 적재 프로세스 수분할 개수로 고정유동적
발생하는 조각외부 조각 + 내부 조각외부 조각

6. 두 종류의 조각

조각(fragmentation)은 쓸 수 있는데 쓰이지 못하는 메모리입니다. 생기는 자리가 다릅니다.

  • 외부 조각(external fragmentation): 분할들 사이사이에 남은 공간. 전부 합치면 충분한데 연속되지 않아 쓸 수 없습니다
  • 내부 조각(internal fragmentation): 할당된 분할 안쪽에 남은 공간. 10MB 영역에 7MB 프로세스를 넣으면 3MB가 쓰이지 못한 채 묶입니다

고정분할은 정해진 칸에 넣으므로 내부 조각이 생기고, 가변분할은 딱 맞게 주므로 내부 조각은 없지만 프로세스가 빠져나간 자리에 외부 조각이 생깁니다.

7. 어느 자리에 넣을 것인가

가변분할에서 비어 있는 공간을 hole이라고 합니다. 크기가 제각각인 여러 hole 중 어디에 넣을지 고르는 문제를 dynamic storage allocation problem이라고 하며, 전략이 셋입니다.

전략동작장점단점
first fit처음 만나는 충분한 hole에 배치탐색이 빨라 가장 빠름배치 품질을 따지지 않음
best fit들어가는 것 중 가장 작은 hole에 배치큰 hole을 보존전체 탐색 필요, 쓸모없이 작은 조각이 많이 남음
worst fit가장 큰 hole에 배치남는 조각이 커서 재사용 가능전체 탐색 필요, 큰 hole이 빨리 사라짐

어느 전략을 써도 외부 조각은 남습니다. 흩어진 조각을 한쪽으로 몰아 하나의 큰 공간으로 만드는 작업이 compaction인데, 실행 중인 프로세스를 옮기는 일이라 비용이 매우 크고 execution time binding일 때만 가능합니다.

결국 연속 할당으로는 한계가 있습니다. 프로세스를 잘게 나눠 흩어진 자리에 올리면 외부 조각 문제가 사라지는데, 이것이 paging과 segmentation입니다.

profile
ML Engineer 🧠 | AI 모델 개발과 최적화 경험을 기록하며 성장하는 개발자 🚀 The light that burns twice as bright burns half as long ✨

0개의 댓글