학교수업, CS/운영체제

물리메모리 관리

빨대도둑 2023. 5. 9. 19:42

메모리 관리

메모리 관리의 이중성: 여러 작업을 동시에 처리할 때 메모리를 어떻게 관리하는지에 대한 문제이다. 복잡한 메모리 관리는 메모리 관리 시스템이 담당한다. 프로세스 입장에서는 메모리를 독차지하려 하고, 메모리 관리자 입장에서는 관리를 효율적으로 하고 싶어 하는데 이를 메모리의 이중성이라고 한다.

일괄 처리 시스템에서는 한 번에 한가지 작업만 처리했기 때문에 메모리 관리가 어렵지 않았지만, 시분할 시스템에서는 운영체제를 포함한 모든 응용 프로그램이 메모리에 올라와 실행되기 때문에 메모리 관리가 복잡하다.

컴파일러를 사용하는 방식에서는 소스코드를 컴퓨터가 실행할 수 있는 기계어로 번역한 후 한꺼번에 실행한다.

인터프리터를 사용하는 방식에서는 소스코드를 한 행씩 번역하여 실행한다.

 

메모리 관리 작업

메모리 관리 작업은 크게 가져오기, 배치, 재배치로 나눈다.

메모리 가져오기: 실행할 프로세스와 데이터를 메모리로 가져오는 작업이다. 그런데 어떤 상황에서는 데이터의 일부만 가져와 실행하기도 한다.

메모리 배치: 가져온 프로세스와 데이터를 메모리의 어떤 부분에 올려 놓을지 결정하는 작업이다. 배치 작업 전에 메모리를 어떤 크기로 자를 것인지가 매우 중요하다. 왜냐하면 크기에 따라서 메모리 관리의 복잡성이 달라지기 때문이다.

페이징: 메모리를 같은 크기로 자르는 것.

세그먼테이션: 프로세스의 크기에 맞게 자르는 것.

배치 정책은 페이징과 세그먼테이션 장단점을 파악하여 메모리를 효율적으로 관리할 수 있도록 정책을 만드는 것이다.

메모리 재배치: 새로운 프로세스를 가져와야 하는데 메모리가 가득 찼다면 메모리에 있는 프로세스를 하드 디스크로 옮겨 놓아야 새로운 프로세스를 메모리에 가져올 수 있다. 이처럼 꽉 찬 메모리에 새로운 프로세스를 가져오기 위해 오래된 프로세스를 내보내는 작업을 메모리 재배치 작업이라고 한다.

 

메모리 오버레이: 실제 메모리 보다 큰 프로그램을 처리하는 방식이다. 프로그램의 크기가 실제 메모리(물리메모리)보다 클 때 전체 프로그램을 메모리에 가져오는 대신 적당한 크기로 잘라서 가져오는 기법이다.

메모리 오버레이는 프로그램을 몇 개의 모듈로 나누고 필요할 때마다 모듈을 메모리에 가져와 사용한다.

메모리 오버레이의 의미

- 한정된 메모리에서 메모리보다 큰 프로그램을 실행할 수 있다.

- 프로그램 전체가 아니라 일부만 메모리에 올라와도 실행할 수 있다. 프로그램은 개념적으로 한 덩어리이지만, 일부분만으로도 실행할 수 있다. 이는 메모리를 여러 조각으로 나누어 여러 프로세스에 할당할 수 있다는 의미이기도 하다.

스왑영역: 메모리가 모자라서 쫓겨난 프로세스를 저장하는 저장장치의 공간(영역)

스왑인: 스왑영역에서 메모리로 데이터를 가져오는 작업

스왑 아웃: 메모리에서 스왑영역으로 데이터를 내보내는 작업

메모리 오버 레이에서는 메모리보다 큰 프로그램을 실행할 때 프로그램의 메모리보다 작은 크기의 모듈로 나누어서 사용한다. 여기에 스왑을 이용하면 스왑영역의 크기가 메모리의 크기로 인식된다. 사용자는 실제 메모리와 스왑영역의 크기를 합쳐서 전체 메모리의 크기로 인식하고 사용할 수 있다.

 

메모리할당

한 번에 여러 프로세스를 동시에 실행하는 경우에는 메모리 관리가 더욱 복잡하다. 프로세스들의 크기가 달라 메모리를 어떻게 나누어 사용할 것인지가 가장 큰 문제이다.

메모리 분할방식

메모리를 어떤 크기로 나눌 것인가는 메모리 배치 정책에 해당한다. 메모리에 여러 개의 프로세스를 배치하는 방법은 가변 분할방식과 고정 분할 방식으로 나눌 수 있다.

가변 분할 방식: 프로세스의 크기에 따라 메모리를 나눈다.

고정 분할 방식: 프로세스의 크기와 상관없이 메모리를 나눈다.

가변 분할 방식에서는 프로세스의 크기에 맞게 메모리가 분할되므로 프로세스가 차지하는 메모리 영역의 크기가 다 다르다. 가변 분할 방식의 장점은 프로세스를 한 덩어리로 처리하여 하나의 프로세스를 연속된 메모리 공간에 배치할 수 있다는 점이다. 가변 분할 방식은 메모리 통합 등의 부가적인 작업이 필요하기 때문에 메모리 관리가 복잡하다.

- 가변 분할 방식은 프로세스의 크기에 맞춰 메모리를 할당하는 방법으로 세그먼테이션메모리 관리기법이라고 한다. 프로세스를 하나의 연속된 주소로 둔 다는 장점이 있다. 프로세스들이 메모리에 올라와 작업을 하다가 종료되면 빈 공간이 생기는데, 가변 분할 방식의 가장 큰 문제점이 바로 이 빈 공간의 크기가 일정하지 않다는 것이다. 가변 분할 방식에서 발생하는 단편화는 조각이 프로세스의 바깥쪽에 위치하기 때문에 외부단편화라고 한다. 외부 단편화로 인한 문제를 해결하기 위해서 메모리 배치 방식이나 조각 모음을 사용한다.

-- 작업보다 많은 공간이 남아 있더라도 실제로 그 작업을 받아들이지 못하는 경우를 외부단편화라고 한다.

-- 메모리 배치 방식: 외부 단편화 문제를 해결하기 위한 대표적인 메모리 배치 방식으로 최초 배치, 최적 배치, 최악 배치, 버디 시스템이 있다.

--- 최초 배치: 단편화를 고려하지 않은 방식으로, 프로세스를 메모리의 빈 공간에 배치할 때 메모리에서 적재 가능한 공간을 순서대로 찾다가 첫 번째 발견한 공간에 프로세스를 배치하는 방법이다.

--- 최적 배치: 메모리의 빈 공간을 모두 확인한 후 크기가 가장 비슷한 곳에 프로세스를 배치하는 방식이다.

--- 최악 배치: 빈 공간을 모두 확보한 후 가장 큰 공간에 프로세스를 배치하는 것으로 최적 배치와 반대되는 개념이다.

-- 조각 모음: 작은 프로세스가 작업을 마치고 메모리에서 나가면 그 공간이 조각으로 남아 쓸모 없어질 가능성이 크다. 이렇게 단편화가 발생하면 이미 배치된 프로세스를 옆으로 옮겨 빈 공간들을 하나의 큰 덩어리로 만들어야 하는데 이 작업이 바로 조각 모임이다. 조각 모음은 서로 떨어져 있는 여러 개의 빈 공간을 합치는 작업으로, 메모리 통합이라고 부르기도 한다.

 

고정분할방식

고정 분할 방식에서는 프로세스의 크기에 상관없이 모두 일정한 크기로 나눈다. 그래서 메모리 관리가 편하다는 장점이 있다. 그리고 메모리 통합 같은 부가적인 작업을 할 필요가 없다. 크기가 큰 프로세스가 메모리에 올라오면 여러 조각으로 나뉘어 배치된다. 고정 분할 방식에서는 하나의 프로세스가 여러 개로 나뉘어 배치되기 때문에 비연속 메모리 할당이라고 한다. 하지만 단점으로는 하자의 프로세스가 여러 곳으로 나뉠 수 있다는 점이 있다.

- 고정 분할 방식을 사용해서 메모리를 나누는 방식을 페이징 메모리 관리 기법이라고 한다. 한 책에서 모든 페이지의 크기가 같기 때문에 페이징이라고 부르는 것이다. 가변 분할 방식과 달리 고정분할 방식은 프로세스의 크기에 상관없이 메모리를 같은 크기로 나누기 때문에 관리하기 편하다. 따라서 현대의 메모리 관리는 페이징을 기본으로 한다. 일정하게 나뉜 메모리의 크기보다 작은 프로세스가 배치될 경우 낭비되는 공간이 생긴다. 이처럼 각 메모리 조각에 프로세스를 배치하고 공간이 남는 것을 내부 단편화라고 한다.

-- 공간이 너무 작아 다른 작업들이 사용하지 못하게 되는데 이러한 작은 빈공간(낭비)들을 내부단편화라고 한다.

-- 가변 분할 방식의 외부 단편화는 조각 모음으로 조정했지만, 고정 분할 방식에서는 내부 단편화를 해결하기 위해 조각 모음을 할 수 없고, 남는 공간을 다른 프로세스에 배정할 수도 없다. 따라서 고정 분할 방식에서는 내부 단편화를 줄이기 위해 메모리를 어떤 크기로 나눌지 신중하게 결정해야 한다.

메모리 오버레이를 다루 때 프로세스가 여러 곳에 나뉘어 배치되거나 일부만 물리 메모리에 있고 나머지는 스왑영역에 있어도 실행에 문제가 없기 때문에 고정 분할 방식은 가변 분할 방식보다 메모리 관리 측면에서 우세하다고 볼 수 있다. 그래서 현대 운영체제에서 메모리 관리는 기본적으로 고정 분할 방식을 사용한다.

버디 시스템: 외부 단편화를 완화하는 방식으로, 가변 분할 방식과 고정 분할 방식의 중간 구조이다. 메모리가 프로세스의 크기대로 나뉘며, 하나의 구역에 다른 프로세스가 들어갈 수 없고, 메모리의 한 구역 내부에 조각이 생겨 내부 단편화가 발생한다

- 효율 적인 공간 관리 측면에서 보면 고정 분할 방식과 비슷한 수준이지만 메모리 관리 측면에서는 공간을 1/2로 나누어 메모리를 배분하기 때문에, 모든 공간을 같은 크기로 나누는 고정 분할 방식보다 복잡하여 버디 시스템보다 고정 분할 방식을 더 많이 사용한다.

 

분할 컴파일

고급 언어로 작성된 소스코드를 기계어로 번역하여 여러 작업을 수행한다. 오류가 있는지 점검하고, 최적화를 통해 필요 없는 변수와 코드를 삭제한다. 이렇게 만들어진 기계어 코드가 목적 코드이다. 실행파일이 만들어지기 전 목적 파일이 만들어지는데 목적 파일은 오류 검사를 거쳐 만든 중간 파일이고, 외부 함수가 비어 있는 상태이다.

여러 개의 소스코드 파일을 사용해서 하나의 실행 파일을 만드는 것을 다중 소스코드라 하고, 여러 개의 소스코드를 각각 컴파일하여 하나의 실행 파일로 만드는 것을 분할 컴파일이라고 한다.

변수를 사용해서 프로그램을 만들면 컴파일러는 모든 변수를 메모리 주소로 바꾸어 기계어로 실행 파일을 만든다. 컴파일러는 변수를 적당한 크기의 메모리 주소로 변환하여 기계어로 만든다. 만들어진 주소는 논리주소이다.