메모리 관리 시스템(memory management system)이란 컴퓨터 시스템에서 메모리를 효율적으로 사용하고 관리하기 위한 기술이다. 메모리 관리 시스템의 주요 목표는 프로세스 간 메모리 공간을 할당하고, 사용되지 않는 메모리를 회수하며, 메모리의 효율적 활용을 위해 조정하는 것이다.
메모리 관리 시스템은 다양한 기능을 제공한다:
메모리 관리 시스템은 컴퓨터 시스템의 운영 체제(OS)에서 주로 관리되며, 하드웨어와 소프트웨어 모두에서 지원된다. 이를 통해 시스템 성능을 향상시키고 자원을 최적화하는 데 도움이 된다.
메모리 관리의 이중성은 시스템 성능과 메모리 사용 효율 사이의 균형을 찾아야 하는 메모리 관리 전략의 중요한 측면이다. 이를 위해 다양한 메모리 관리 기법이 공간 효율성(메모리 낭비 최소화)과 시간 효율성(빠른 메모리 접근) 사이의 최적의 절충안을 찾으려고 노력한다.
컴파일러는 실행 전에 소스 코드를 점검하여 오류를 수정하고 필요 없는 부분을 정리하여 최적화된 실행 파일을 만든다.
컴파일러를 사용하는 언어는 사용할 변수를 먼저 선언한 후 코드를 작성해야 한다.
어휘 분석(Lexical Analysis): 소스 코드를 읽어 토큰(token)이라 불리는 의미 있는 요소로 분리한다. 이 단계에서 주석, 공백 등은 제거된다.
구문 분석(Parsing): 어휘 분석에서 생성된 토큰들을 구문 규칙(syntax)에 따라 추상 구문 트리(Abstract Syntax Tree, AST)와 같은 중간 표현 형태로 변환한다.
의미 분석(Semantic Analysis): 추상 구문 트리에서 의미 오류를 검사하고, 변수와 함수의 정의 및 사용에 대한 정보를 확인한다. 이 과정에서 타입 검사(type checking)도 수행된다.
중간 코드 생성(Intermediate Code Generation): 의미 분석을 통해 검증된 추상 구문 트리를 중간 코드(Intermediate Code)로 변환한다. 이 중간 코드는 소스 코드와 기계어 사이의 표현이며, 이를 통해 최적화 및 기계어 변환을 수행합니다.
코드 최적화(Code Optimization): 중간 코드를 분석하여 불필요한 연산이나 반복을 제거하고, 코드의 효율성을 높이는 최적화 작업을 수행한다.
목적 코드 생성(Target Code Generation): 최적화된 중간 코드를 기계어로 변환하여 실행 가능한 목적 코드(Object Code)를 생성합니다. 이 단계에서 메모리 주소 및 레지스터 할당이 이루어진다. 확장자는 obj다.
링킹(Linking): 목적 코드와 필요한 라이브러리 파일을 연결해 완전한 실행 파일을 생성한다. 이 과정에서 함수 호출 및 라이브러리 참조를 해결하며, 최종 실행 파일이 생성된다.
동적 라이브러리(dynamic library)는 프로그램 실행 중에 필요한 코드나 데이터를 로드하고 사용할 수 있는 라이브러리다. 동적 라이브러리는 공유 라이브러리(shared library)라고도 불리며, 확장자로 .so (리눅스), .dll (윈도우) 등을 사용한다.
메모리를 접근할 때는 주소를 이용한다. 메모리 주소는 물리 주소와 논리 주소로 나뉜다.
CPU를 나타낼 때 비트(bit)는 CPU가 한 번에 다룰 수 있는 최대 크기를 의미한다.
논리 주소(logical address):
논리 주소는 프로세스에 의해 생성되고 사용되는 주소이다. 프로세스는 가상 메모리 공간에서 실행되며, 논리 주소는 이 가상 메모리 공간에서 데이터를 찾기 위해 사용된다. 논리 주소는 CPU에 의해 생성되며, 가상 메모리 관리 시스템을 사용하여 물리 주소로 변환된다. (각 프로그램 마다 0번지 부터 시작하는 주소)
물리 주소(physical address):
물리 주소는 실제 메모리 하드웨어(예: RAM)에 저장된 데이터의 위치를 나타낸다. 논리 주소가 물리 주소로 변환되면, 컴퓨터는 실제 메모리에서 해당 데이터를 읽거나 쓸 수 있다. 물리 주소는 메모리 관리 장치(MMU)를 통해 논리 주소에서 파생된다.
경계 레지스터(boundary register)는 메모리 프로텍션 및 관리에 사용되는 하드웨어 레지스터이다. 이 레지스터는 프로세스가 할당받은 메모리 영역의 경계를 저장하며, 프로세스가 다른 프로세스의 메모리 공간에 접근하지 못하도록 보호하는 역할을 한다.
경계 레지스터는 주로 베이스 레지스터(base register)와 함께 사용되어 메모리 접근을 관리한다. 베이스 레지스터는 프로세스가 할당받은 메모리 공간의 시작 주소를 저장하고, 경계 레지스터는 해당 메모리 공간의 크기 또는 끝 주소를 저장한다.
프로세스가 메모리에 접근하려 할 때, 베이스 레지스터와 경계 레지스터의 값은 CPU에 의해 비교된다. 만약 접근하려는 주소가 베이스 레지스터와 경계 레지스터가 나타내는 영역 내에 있으면, 메모리 접근이 허용된다. 그렇지 않으면 메모리 접근이 거부되고 오류가 발생한다.
이와 같이 경계 레지스터는 메모리 프로텍션 및 관리를 위해 사용되며, 프로세스가 할당받은 메모리 영역의 경계를 저장하여 프로세스 간 메모리 공간의 침범을 방지한다.
메모리 오버레이(memory overlay)는 컴퓨터 프로그램이 메모리 부족 문제를 해결하기 위해 사용하는 기법이다. 이 기법은 주로 작은 메모리 용량을 가진 시스템에서 큰 프로그램을 실행할 때 사용되며, 메모리에 동시에 저장할 수 없는 프로그램의 여러 부분을 시간에 따라 교체하며 실행한다.
메모리 오버레이의 주요 개념은 프로그램을 여러 개의 작은 모듈로 분리한 다음, 필요할 때 마다 모듈을 메모리에 가져와 사용한다
스왑(swap)은 컴퓨터에서 메모리 관리를 위해 사용되는 기법으로, 물리 메모리(RAM)가 부족할 때 디스크 공간을 사용하여 프로세스와 데이터를 일시적으로 저장하는 과정이다. 스왑은 가상 메모리 시스템에서 중요한 역할을 하며, 메모리를 효율적으로 사용하고 더 많은 프로세스를 실행할 수 있게 한다.
스왑 과정은 다음과 같다:
물리 메모리가 부족한 상황이 발생하면, 운영 체제는 사용 중인 메모리 중 일부를 디스크의 스왑 영역(swap area)으로 이동시킨다. 이를 스왑 아웃(swap out)이라고 한다.
필요한 프로세스나 데이터가 스왑 영역에 있는 경우, 운영 체제는 디스크에서 해당 프로세스나 데이터를 다시 물리 메모리로 불러온다. 이를 스왑 인(swap in)이라고 한다.
스왑을 사용하면 물리 메모리가 부족할 때 추가적인 메모리 공간을 확보할 수 있지만, 디스크에 접근하는 속도가 물리 메모리에 접근하는 속도보다 훨씬 느리기 때문에 성능 저하가 발생할 수 있다 따라서 스왑은 메모리 부족 문제를 해결하는 일시적인 방법으로 사용되며, 성능을 향상시키려면 물리 메모리 용량을 늘리는 것이 좋다.
가변 분할 방식(variable partitioning method)과 고정 분할 방식(fixed partitioning method)은 메모리 관리에서 사용되는 두 가지 주요 분할 방식입니다. 이들 방식은 각각 다음과 같은 특징을 가집니다.
외부 단편화(external fragmentation): 조각이 프로세스의 바깥쪽에 위치 하는 것
최초 배치(First Fit):
최초 배치 알고리즘은 메모리를 순차적으로 검색하여 프로세스가 사용할 수 있는 충분한 공간을 찾는 첫 번째 빈 메모리 공간에 할당하는 방식.
최적 배치(Best Fit):
최적 배치 알고리즘은 프로세스가 필요로 하는 메모리 크기에 가장 가까운 빈 메모리 공간을 찾아 할당하는 방식.
최악 배치(Worst Fit):
최악 배치 알고리즘은 사용 가능한 빈 메모리 공간 중 가장 큰 공간에 프로세스를 할당하는 방식.
조각 모음(defragmentation)은 서로 떨어져 있는 여러 개의 빈 공간을 합치는 작업이다.
조각 모음은 다음과 같은 순서로 진행된다.
1. 조각 모음을 하기 위해 이동할 프로세스의 동작을 멈춘다.
2. 프로세스를 적당한 위치로 이동한다. 프로세스가 원래의 위치에서 이동하기 때문에 프로세스의 논리 주소 값을 바꾼다.
3. 앞의 1, 2 작업을 다 마친 후 프로세스를 다시 시작한다.
버디 시스템은 가변 분할 방식과 고정 분할 방식의 중간 구조다.