메모리 구조
1. 개요
1. 개요
메모리 구조는 컴퓨터 시스템이 데이터와 명령어를 저장하고 관리하기 위한 하드웨어 및 소프트웨어적 구성 요소들의 체계를 가리킨다. 이 구조는 프로그램의 실행, 데이터의 임시 저장, 그리고 영구적인 데이터 보관 등 다양한 목적을 위해 설계된다.
주요 구성 요소는 속도와 용량에 따라 다단계의 계층 구조를 이루며 배열된다. 가장 빠른 레지스터와 캐시 메모리는 중앙 처리 장치(CPU)와 직접 소통하며, 그 다음으로 주기억장치(RAM)가 프로그램이 실행되는 공간을 제공한다. 대용량이지만 상대적으로 느린 보조기억장치(HDD, SSD)는 데이터를 영구적으로 보관하는 역할을 담당한다.
이러한 물리적 메모리 계층은 운영체제에 의해 효율적으로 관리되며, 프로세스마다 독립적인 논리적 주소 공간을 할당받는다. 이 논리적 공간은 일반적으로 코드 영역, 데이터 영역, 힙 영역, 스택 영역으로 구분되어 프로그램의 안정적인 실행을 보장한다.
메모리 구조에 대한 이해는 컴퓨터 구조 설계, 운영체제의 메모리 관리 기법 구현, 그리고 프로그래밍 시 메모리 할당과 성능 최적화를 수행하는 데 필수적인 기초 지식이다.
2. 주 메모리 계층 구조
2. 주 메모리 계층 구조
2.1. 레지스터
2.1. 레지스터
레지스터는 중앙 처리 장치 내부에 위치한, 가장 빠른 속도를 가진 소규모의 고속 기억 장치이다. 프로세서가 직접 접근하여 사용하며, 현재 실행 중인 명령어나 연산에 필요한 데이터를 임시로 보관하는 역할을 한다. 용량은 매우 작지만, CPU의 연산 속도에 직접적인 영향을 미치는 핵심적인 자원이다.
레지스터는 그 용도에 따라 여러 종류로 구분된다. 프로그램 카운터는 다음에 실행할 명령어의 주소를 저장하고, 명령어 레지스터는 현재 실행 중인 명령어 자체를 보관한다. 누산기는 산술 논리 연산의 결과를 임시 저장하며, 주소 레지스터와 데이터 레지스터는 메모리 접근 시 주소와 데이터를 각각 전달한다. 또한 플래그 레지스터는 연산 결과의 상태(예: 오버플로, 제로)를 나타내는 플래그 비트들을 포함한다.
이러한 레지스터들은 어셈블리어 수준의 프로그래밍에서 직접적으로 접근하거나 제어할 수 있으며, 컴파일러가 생성하는 기계어 코드의 효율성을 결정하는 중요한 요소가 된다. 메모리 계층 구조의 최상위에 위치한 레지스터는 처리 속도를 극대화하기 위해 캐시 메모리나 주기억장치보다 훨씬 빠른 반도체 소자로 구현된다.
2.2. 캐시 메모리
2.2. 캐시 메모리
캐시 메모리는 CPU와 주기억장치 사이에 위치하는 고속의 소규모 메모리이다. 메모리 계층 구조에서 레지스터 다음으로 가장 빠른 접근 속도를 가지며, CPU가 자주 사용하는 데이터나 명령어를 미리 저장해 두어 전체적인 시스템 성능을 향상시키는 역할을 한다. 이는 CPU의 처리 속도와 상대적으로 느린 주기억장치의 접근 속도 간의 차이, 즉 폰 노이만 병목 현상을 완화하기 위한 핵심 장치이다.
캐시 메모리의 동작은 지역성의 원리에 기반한다. 이 원리는 시간 지역성과 공간 지역성으로 나뉘는데, 시간 지역성은 최근에 접근한 데이터가 가까운 미래에 다시 접근될 가능성이 높다는 것이고, 공간 지역성은 특정 데이터에 접근하면 그 주변의 데이터에도 접근할 가능성이 높다는 것이다. 캐시는 이러한 특성을 활용해 필요한 데이터를 예측하여 저장함으로써 메모리 접근 시간을 단축한다.
캐시 메모리는 일반적으로 L1 캐시, L2 캐시, L3 캐시와 같이 여러 단계로 구성된다. L1 캐시는 CPU 코어 내부에 통합되어 속도가 가장 빠르고 용량이 가장 작으며, 명령어 캐시와 데이터 캐시로 분리되어 있는 경우가 많다. L2와 L3 캐시는 점점 더 큰 용량과 느린 속도를 가지며, 여러 코어가 공유하는 형태로 구성되기도 한다. 캐시의 성능은 히트율로 평가되며, 요청한 데이터가 캐시에 존재하는 경우를 히트, 존재하지 않아 주기억장치에서 가져와야 하는 경우를 미스라고 한다.
캐시 메모리의 데이터 관리 방식에는 캐시 매핑 기법이 중요한데, 이는 주기억장치의 특정 블록이 캐시의 어느 위치에 저장될지 결정하는 규칙이다. 주요 매핑 방식으로는 직접 매핑, 완전 연관 매핑, 집합 연관 매핑이 있으며, 각각 장단점이 있다. 또한 캐시 내 데이터의 일관성을 유지하기 위한 캐시 일관성 프로토콜은 멀티코어 프로세서 시스템에서 특히 중요하게 작동한다.
2.3. 주기억장치 (RAM/ROM)
2.3. 주기억장치 (RAM/ROM)
주기억장치는 컴퓨터가 현재 실행 중인 프로그램과 그 프로그램이 처리하는 데이터를 일시적으로 저장하는 주요 저장 공간이다. 이는 중앙 처리 장치가 직접 접근하여 빠르게 읽고 쓸 수 있는 휘발성 메모리로, 시스템의 작업 성능을 결정하는 핵심 요소이다. 주기억장치는 크게 램과 롬으로 구분된다.
램은 임의 접근 메모리로, 데이터를 자유롭게 읽고 쓸 수 있으며 전원이 공급되는 동안만 정보를 유지한다. 램은 다시 동적 램과 정적 램으로 나뉜다. 동적 램은 주기적인 재충전이 필요하지만 집적도가 높아 대용량 주기억장치로 주로 사용된다. 반면 정적 램은 재충전이 필요 없어 속도가 매우 빠르지만, 집적도가 낮고 가격이 비싸 캐시 메모리 등에 사용된다.
롬은 읽기 전용 메모리로, 제조 시 또는 특별한 방법으로 한 번 기록된 데이터는 전원이 꺼져도 영구히 보존된다. 롬은 컴퓨터의 기본 입출력 시스템이나 펌웨어처럼 변경이 거의 필요 없는 프로그램을 저장하는 데 사용된다. 롬의 변형으로 사용자가 한 번만 기록할 수 있는 프롬, 자외선으로 지우고 다시 쓸 수 있는 이프롬, 전기적으로 여러 번 재기록이 가능한 이이프롬 등이 있다.
주기억장치의 용량과 속도는 시스템 전체의 성능에 직접적인 영향을 미친다. 램의 용량이 충분해야 여러 응용 프로그램을 동시에 원활하게 실행할 수 있으며, 램의 동작 속도는 중앙 처리 장치가 데이터를 처리하는 속도의 병목 현상을 줄이는 데 중요하다. 따라서 메모리 계층 구조에서 램은 캐시 메모리와 보조기억장치 사이의 균형점을 이루는 핵심 계층으로 작동한다.
2.4. 보조기억장치
2.4. 보조기억장치
보조기억장치는 주기억장치보다 속도는 느리지만, 훨씬 큰 용량을 가지고 데이터를 영구적으로 보관하는 역할을 한다. 중앙처리장치가 직접 접근하지 않으며, 필요한 프로그램이나 데이터는 주기억장치로 불러와서 사용한다. 따라서 컴퓨터가 꺼져도 데이터가 사라지지 않는 비휘발성 저장 장치의 특성을 가진다.
과거에는 하드 디스크 드라이브와 광학 디스크 드라이브, 자기 테이프 등이 주로 사용되었으나, 현대에는 솔리드 스테이트 드라이브가 빠른 속도와 내구성으로 널리 보급되었다. 또한 USB 플래시 드라이브와 메모리 카드와 같은 휴대용 저장 매체도 보조기억장치의 일종이다.
보조기억장치는 운영체제, 응용 소프트웨어, 사용자 문서, 미디어 파일 등 모든 종류의 데이터를 장기간 저장하는 데 사용된다. 데이터베이스 관리나 멀티미디어 콘텐츠 저장과 같이 대용량 저장 공간이 필요한 작업에 필수적이다. 이는 메모리 계층 구조에서 가장 아래쪽에 위치하며, 용량 대비 비용이 가장 저렴한 계층이다.
최근에는 클라우드 스토리지 서비스가 발전하면서, 물리적인 로컬 보조기억장치를 넘어 네트워크를 통해 접근하는 온라인 저장 공간도 중요한 저장 수단으로 자리 잡고 있다.
3. 프로세스 메모리 구조
3. 프로세스 메모리 구조
3.1. 코드 영역 (Text Segment)
3.1. 코드 영역 (Text Segment)
코드 영역은 프로세스의 메모리 구조에서 실행 가능한 기계어 명령어들이 저장되는 영역이다. 이 영역은 텍스트 세그먼트라고도 불리며, 읽기 전용 메모리 속성을 가진다. 프로그램의 주요 실행 코드, 즉 함수와 제어문 등의 로직이 이곳에 위치하게 되어 중앙 처리 장치가 순차적으로 명령어를 인출하고 실행한다.
코드 영역은 일반적으로 메모리 보호를 위해 쓰기 작업이 금지되어 있다. 이는 실행 중인 프로그램 코드가 의도치 않게 변경되는 것을 방지하여 시스템의 안정성을 높이는 역할을 한다. 운영체제는 가상 메모리 시스템을 통해 각 프로세스에 독립적인 코드 영역을 할당하며, 동일한 프로그램의 여러 인스턴스가 실행될 경우 물리 메모리에는 하나의 코드 영역만 로드하고 이를 공유하는 방식으로 메모리 사용 효율을 높이기도 한다.
이 영역의 크기는 프로그램이 컴파일 또는 링크되는 시점에 결정되며, 실행 중에는 크기가 고정된다. 코드 영역의 내용은 보조기억장치에 저장된 실행 파일의 텍스트 섹션에서 로드된다. 코드 영역의 효율적인 관리와 접근은 캐시 메모리와의 연계를 통해 전체 시스템 성능에 직접적인 영향을 미치는 중요한 요소이다.
3.2. 데이터 영역 (Data Segment)
3.2. 데이터 영역 (Data Segment)
데이터 영역은 프로세스의 가상 주소 공간을 구성하는 주요 세그먼트 중 하나로, 프로그램의 전역 변수와 정적 변수가 할당되는 메모리 공간이다. 이 영역은 프로그램이 시작될 때 운영체제에 의해 할당되며, 프로그램이 종료될 때까지 유지된다. 데이터 영역은 다시 초기화된 데이터 세그먼트와 초기화되지 않은 데이터 세그먼트로 나뉜다. 초기화된 데이터 세그먼트에는 선언과 동시에 초기값이 할당된 전역 및 정적 변수가 저장되고, 초기화되지 않은 데이터 세그먼트(BSS)는 초기값 없이 선언된 변수들이 위치하며, 프로그램 시작 시 0으로 초기화된다.
데이터 영역의 주요 특징은 프로그램의 생명주기 동안 그 크기가 고정되어 있다는 점이다. 즉, 컴파일 또는 링킹 시점에 필요한 메모리 공간의 크기가 결정되며, 실행 중에 동적으로 크기가 변하지 않는다. 이는 실행 중에 크기가 변할 수 있는 힙 영역이나 스택 영역과 대비되는 특징이다. 데이터 영역에 저장된 변수들은 모든 함수에서 접근 가능한 전역적인 수명을 가지며, 메모리 관리 측면에서 사전에 예측 가능한 공간을 차지한다.
이 영역의 메모리는 주기억장치에 상주하며, 가상 메모리 시스템을 통해 관리된다. 운영체제는 각 프로세스에 독립적인 가상 주소 공간을 제공하며, 데이터 영역은 그 안에 논리적으로 매핑된다. 데이터 영역의 변수들에 대한 접근은 논리 주소를 통해 이루어지며, 메모리 관리 장치에 의해 실제 물리 주소로 변환된다. 이 과정에서 페이지 테이블과 같은 메모리 관리 기법이 사용된다.
데이터 영역의 사용은 메모리 보호와도 깊은 연관이 있다. 운영체제는 일반적으로 데이터 영역을 읽기와 쓰기가 가능한 영역으로 설정하지만, 필요에 따라 접근 권한을 조절할 수 있다. 예를 들어, 상수 형태의 전역 데이터는 읽기 전용으로 설정되어 의도치 않은 변경을 방지한다. 이는 프로그램의 안정성과 보안을 유지하는 데 중요한 역할을 한다.
3.3. 힙 영역 (Heap Segment)
3.3. 힙 영역 (Heap Segment)
힙 영역은 프로세스의 가상 주소 공간에서 런타임에 동적으로 할당되는 메모리 공간이다. 이 영역은 프로그래머가 직접 관리하며, C나 C++ 같은 언어에서는 malloc, calloc, new와 같은 함수나 연산자를 통해 메모리를 할당받고, free나 delete를 통해 해제한다. 힙 영역은 주로 프로그램 실행 중에 크기가 예측 불가능한 데이터 구조(예: 연결 리스트, 트리)나 수명이 예측하기 어려운 객체를 저장하는 데 사용된다.
힙 영역은 일반적으로 낮은 주소에서 높은 주소 방향으로(즉, 위쪽으로) 공간이 증가한다. 이는 반대 방향으로 증가하는 스택 영역과 대비되는 특징이다. 힙 메모리의 할당과 해제는 특정 순서를 따르지 않기 때문에, 사용이 반복되면 메모리 공간에 빈 공간(단편)이 생기는 메모리 단편화 현상이 발생할 수 있다. 이는 전체적인 메모리 사용 효율을 저하시킬 수 있는 문제점이다.
힙 메모리 관리는 운영체제의 메모리 관리자와 프로그래밍 언어의 런타임 라이브러리(가비지 컬렉터 포함)가 담당한다. 자바나 파이썬과 같은 언어는 가비지 컬렉션 기능을 통해 사용되지 않는 힙 메모리를 자동으로 회수하여 프로그래머의 부담을 줄인다. 잘못된 힙 메모리 관리(예: 해제하지 않은 할당, 이미 해제된 메모리 참조)는 메모리 누수나 세그멘테이션 폴트와 같은 심각한 오류를 초래할 수 있다.
3.4. 스택 영역 (Stack Segment)
3.4. 스택 영역 (Stack Segment)
스택 영역은 프로세스의 가상 주소 공간을 구성하는 주요 부분 중 하나이다. 이 영역은 함수 호출과 지역 변수 저장을 관리하기 위해 사용되는 메모리 구역으로, LIFO 방식으로 데이터를 저장하고 제거한다. 운영체제는 각 프로그램이 실행될 때 독립적인 스택 영역을 할당하며, 이는 컴파일 시점에 크기가 결정되는 정적 영역이 아니라 프로그램 실행 중에 동적으로 변화한다.
스택 영역의 주요 역할은 함수 호출 시의 실행 컨텍스트를 관리하는 것이다. 함수가 호출되면 반환 주소, 인자, 그리고 함수 내부의 지역 변수가 스택에 푸시된다. 함수 실행이 종료되면 이 정보들이 팝되어 제거되고, CPU는 저장된 반환 주소로 돌아가 다음 명령을 실행한다. 이러한 방식은 재귀 호출을 포함한 복잡한 프로그램 흐름을 효율적으로 지원한다.
스택 영역은 일반적으로 가상 주소 공간의 높은 주소에서 낮은 주소 방향으로 성장한다. 이 영역에 할당되는 메모리는 연속적이며, 스택 포인터라는 특수 레지스터가 현재 스택의 최상단 위치를 가리킨다. 스택의 크기는 제한되어 있어, 너무 많은 함수 호출이나 큰 지역 변수 할당으로 인해 스택이 할당된 경계를 넘어서면 스택 오버플로우 오류가 발생한다. 이는 프로그램의 비정상 종료를 유발할 수 있다.
스택 영역은 힙 영역과 대비되는 개념이다. 힙 영역이 프로그래머가 명시적으로 할당하고 해제하는 동적 메모리 공간이라면, 스택 영역의 할당과 해제는 함수 호출과 반환에 따라 자동으로 이루어진다. 또한 스택에 저장된 데이터는 해당 함수의 수명을 따르기 때문에 메모리 관리가 간단하다는 장점이 있다. 이 영역의 동작 원리는 어셈블리어 수준의 프로그래밍과 디버깅에서도 중요한 기초가 된다.
4. 가상 메모리
4. 가상 메모리
4.1. 페이징
4.1. 페이징
페이징은 운영체제가 가상 메모리를 관리하는 주요 기법 중 하나이다. 이 기법은 프로세스가 사용하는 가상 주소 공간을 고정 크기의 블록인 페이지로 나누고, 실제 물리 메모리도 같은 크기의 프레임으로 나누어 관리한다. 각 프로세스의 페이지는 필요에 따라 물리 메모리의 어떤 프레임에도 할당될 수 있으며, 이 매핑 정보는 페이지 테이블에 저장된다. 이를 통해 프로세스가 필요로 하는 모든 코드와 데이터를 물리 메모리에 연속적으로 배치할 필요가 없어져, 메모리 단편화 문제를 효과적으로 해결한다.
페이징 시스템의 핵심은 가상 주소를 물리 주소로 변환하는 작업이다. CPU가 생성한 가상 주소는 페이지 번호와 페이지 오프셋으로 분리된다. 페이지 번호는 페이지 테이블의 인덱스로 사용되어 해당 페이지가 저장된 물리 메모리의 프레임 번호를 찾아내고, 이 프레임 번호와 페이지 오프셋을 결합하여 최종 물리 주소를 얻는다. 이 변환 과정은 MMU라는 하드웨어 장치가 담당하여 고속으로 처리된다.
페이징 기법은 메모리 보호와 공유를 용이하게 한다. 각 페이지 테이블 항목에는 해당 페이지에 대한 읽기/쓰기/실행 권한 정보가 포함되어 있어, 프로세스가 허가되지 않은 메모리 영역에 접근하는 것을 방지할 수 있다. 또한 여러 프로세스가 공통으로 사용하는 코드나 데이터를 담은 페이지는 물리 메모리의 동일한 프레임에 매핑하여 메모리 공유를 구현할 수 있어 메모리 사용 효율을 높인다.
물리 메모리가 가득 차면 운영체제는 페이지 교체 알고리즘을 사용하여 사용 빈도가 낮은 페이지를 선택해 보조기억장치의 스왑 영역으로 내보내고, 필요한 새로운 페이지를 그 자리에 불러온다. 이 과정을 페이지 교체라고 하며, FIFO, LRU, 최적 페이지 교체 등의 다양한 알고리즘이 사용된다. 페이지 교체가 너무 빈번하게 발생하는 스레싱 현상은 시스템 성능을 급격히 저하시킬 수 있다.
4.2. 세그멘테이션
4.2. 세그멘테이션
세그멘테이션은 가상 메모리를 관리하는 기법 중 하나로, 프로세스의 논리적 주소 공간을 의미 있는 단위인 세그먼트로 나누어 관리한다. 페이징 기법이 고정된 크기의 페이지로 나누는 것과 달리, 세그멘테이션은 코드, 데이터, 스택과 같이 기능이나 구조에 따라 가변적인 크기의 단위로 분할한다. 각 세그먼트는 독립적인 논리적 단위이므로, 서로 다른 프로세스 간에 세그먼트를 공유하거나 보호 정책을 적용하기가 상대적으로 용이하다는 장점이 있다.
이 기법에서 프로세스의 논리적 주소는 세그먼트 번호와 세그먼트 내 오프셋으로 구성된다. 운영체제는 각 프로세스마다 세그먼트 테이블을 유지하며, 이 테이블에는 각 세그먼트의 기준 주소와 한계 길이 정보가 저장된다. 메모리 관리 장치는 논리적 주소를 물리적 주소로 변환할 때, 세그먼트 번호로 테이블을 참조해 기준 주소를 얻고, 오프셋이 세그먼트의 한계 길이 내에 있는지 검사한 후 두 값을 더하여 실제 주기억장치 주소를 계산한다.
그러나 세그멘테이션은 외부 단편화 문제를 야기할 수 있다. 각 세그먼트의 크기가 가변적이기 때문에 메모리에 가변 크기의 빈 공간들이 산발적으로 생기고, 이로 인해 총 여유 공간은 충분함에도 새로운 세그먼트를 할당할 수 없는 상황이 발생할 수 있다. 이 문제를 완화하기 위해 메모리 압축 기법이 사용되기도 하지만, 이는 상당한 오버헤드를 동반한다. 이러한 단점으로 인해 현대 운영체제는 순수한 세그멘테이션보다는 페이징과 세그멘테이션을 결합한 세그멘테이션-페이징 혼용 기법을 더 많이 사용하는 경향이 있다.
5. 메모리 관리 기법
5. 메모리 관리 기법
5.1. 연속 메모리 할당
5.1. 연속 메모리 할당
연속 메모리 할당은 운영체제가 프로세스에게 필요한 메모리 공간을 물리적 주소 공간에서 연속된 하나의 블록으로 할당하는 기법이다. 이 방식은 초기 운영체제에서 널리 사용되었으며, 메모리 관리의 기본적인 방법 중 하나에 해당한다. 연속 할당은 메모리를 프로세스의 크기와 동일한 단일한 연속 구역으로 제공하여 구현이 비교적 단순하다는 장점을 지닌다.
연속 메모리 할당의 대표적인 방식으로는 최초 적합, 최적 적합, 최악 적합 알고리즘이 있다. 최초 적합은 사용 가능한 공간 중 첫 번째로 발견된 충분히 큰 공간에 프로세스를 할당한다. 최적 적합은 요구 크기와 가장 비슷한 크기의 공간을 찾아 할당하며, 최악 적합은 가장 큰 공간에 프로세스를 배치하여 남는 공간을 최대화하려는 전략이다. 이러한 알고리즘들은 메모리 단편화 문제를 완화하기 위해 고안되었다.
연속 할당 방식은 내부 단편화와 외부 단편화라는 심각한 문제를 야기한다. 내부 단편화는 할당된 메모리 블록 내에서 프로세스가 실제 사용하지 않는 남는 공간이 발생하는 현상이다. 외부 단편화는 메모리 전체적으로는 충분한 공간이 존재하지만, 그 공간들이 작고 분산되어 있어 새로운 프로세스를 할당할 수 없는 상태를 말한다. 외부 단편화를 해결하기 위해 압축 기법이 사용되기도 하지만, 이는 시스템에 큰 오버헤드를 초래한다.
이러한 단점들로 인해 현대 운영체제에서는 페이징이나 세그멘테이션과 같은 불연속 메모리 할당 기법이 주로 사용된다. 그러나 연속 메모리 할당은 메모리 관리의 역사적 발전 과정을 이해하는 데 중요한 개념이며, 특정 임베디드 시스템이나 제한된 환경에서는 여전히 활용될 수 있다.
5.2. 불연속 메모리 할당
5.2. 불연속 메모리 할당
불연속 메모리 할당은 프로세스의 논리적 주소 공간을 여러 개의 블록으로 나누어, 물리적 메모리의 서로 다른 위치에 비연속적으로 배치하는 방식이다. 이는 연속 메모리 할당 방식에서 발생하는 외부 단편화 문제를 해결하고 메모리 이용 효율을 높이기 위해 고안되었다. 대표적인 불연속 할당 기법으로는 페이징과 세그멘테이션이 있으며, 현대 운영체제에서는 이 둘을 결합한 세그먼트-페이징 혼용 기법을 사용하기도 한다.
페이징 기법은 프로세스의 주소 공간을 고정된 크기의 페이지로 자르고, 물리 메모리 역시 같은 크기의 프레임으로 나누어 페이지를 프레임에 할당한다. 각 프로세스는 자신의 페이지 테이블을 가지며, 이를 통해 논리적 페이지 번호를 물리적 프레임 번호로 변환한다. 이 방식은 외부 단편화를 완전히 제거하지만, 내부 단편화가 발생할 수 있다는 특징이 있다.
반면 세그멘테이션 기법은 프로세스를 논리적 의미 단위인 세그먼트(예: 코드, 데이터, 스택)로 나누어 할당한다. 각 세그먼트는 가변 길이를 가지며, 세그먼트 테이블을 통해 논리 주소를 물리 주소로 변환한다. 이 방식은 프로그래머의 관점에 부합하고 보안과 공유에 유리하지만, 외부 단편화 문제가 여전히 발생할 수 있다는 단점이 있다.
이러한 불연속 할당 기법들은 가상 메모리 시스템의 핵심을 이루며, MMU와 같은 하드웨어 지원을 통해 효율적으로 구현된다. 이를 통해 시스템은 한정된 물리 메모리보다 훨씬 큰 주소 공간을 프로세스에 제공할 수 있게 되었다.
5.3. 메모리 보호
5.3. 메모리 보호
메모리 보호는 운영체제가 여러 프로세스가 동시에 실행되는 다중 프로그래밍 환경에서, 하나의 프로세스가 다른 프로세스의 메모리 영역이나 운영체제 자체의 메모리 영역을 불법적으로 접근하거나 변경하는 것을 방지하는 기법이다. 이는 시스템의 안정성과 보안을 유지하는 데 핵심적인 역할을 한다. 메모리 보호가 없다면, 한 프로그램의 오류나 악의적인 코드가 전체 시스템을 다운시키거나 중요한 데이터를 훼손할 수 있다.
메모리 보호를 구현하는 주요 하드웨어 기반 메커니즘으로는 베이스 레지스터와 한계 레지스터 쌍을 사용하는 방법이 있다. 베이스 레지스터는 프로세스가 할당받은 물리적 메모리의 시작 주소를, 한계 레지스터는 프로세스의 최대 크기를 저장한다. CPU가 메모리에 접근할 때마다, 접근하려는 논리 주소가 한계 레지스터의 값보다 작은지 확인하고, 베이스 레지스터 값을 더해 물리 주소로 변환한다. 이 과정에서 한계를 벗어나는 접근 시도는 트랩을 발생시켜 운영체제가 개입하도록 한다.
또 다른 중요한 메모리 보호 수단은 가상 메모리 시스템에서 사용되는 페이지 테이블의 접근 권한 비트이다. 각 페이지 또는 세그먼트에는 읽기, 쓰기, 실행과 같은 권한 정보가 부여된다. 예를 들어, 코드 영역은 일반적으로 읽기와 실행만 가능하도록 설정되어, 악의적인 코드가 해당 영역에 데이터를 써서 프로그램의 동작을 변경하는 것을 막는다. 이러한 권한 위반 시 페이지 폴트나 세그멘테이션 폴트가 발생하여 운영체제에 통보된다.
메모리 보호는 커널 모드와 사용자 모드라는 프로세서의 특권 수준 개념과 밀접하게 연관되어 있다. 운영체제 커널은 커널 모드에서 모든 메모리 영역과 하드웨어 자원에 접근할 수 있지만, 사용자 애플리케이션은 사용자 모드에서 실행되어 제한된 메모리 영역만 접근할 수 있다. 사용자 프로세스가 특권 명령이나 보호된 메모리 영역에 접근하려 하면 인터럽트가 발생하여 운영체제가 이를 차단한다. 이 이중 모드 운영은 시스템의 핵심 부분을 사용자 프로그램의 오류로부터 보호하는 기본적인 장치이다.
6. 주요 개념
6. 주요 개념
6.1. 주소 바인딩
6.1. 주소 바인딩
주소 바인딩은 프로그램이 사용하는 논리적 주소를 실제 물리 메모리의 주소로 변환하는 과정을 의미한다. 프로그램이 컴파일될 때 생성되는 주소는 일반적으로 0번지부터 시작하는 논리적 주소 공간이며, 이 주소는 프로그램이 실행되어 실제 메모리에 적재될 때 비로소 물리적 주소로 결정된다. 이 변환 작업은 운영체제와 하드웨어(메모리 관리 장치)가 협력하여 수행한다.
주소 바인딩 시점에 따라 컴파일 타임 바인딩, 로드 타임 바인딩, 실행 시간 바인딩으로 구분된다. 컴파일 타임 바인딩은 프로그램이 컴파일되는 시점에 물리 주소가 결정되며, 이후 위치를 변경할 수 없다. 로드 타임 바인딩은 프로그램이 메모리에 적재되는 시점에 주소가 바인딩되며, 재배치 가능 코드를 생성한다. 가장 일반적인 방식은 실행 시간 바인딩으로, 프로그램 실행 중에도 물리 메모리 상의 위치가 변경될 수 있으며, 이 경우 하드웨어 지원(예: 베이스 레지스터와 한계 레지스터)을 통해 주소 변환이 실시간으로 이루어진다.
실행 시간 바인딩은 가상 메모리 시스템의 핵심 개념이다. 프로세스가 사용하는 가상 주소는 페이징이나 세그멘테이션 기법을 통해 동적으로 물리 주소로 매핑된다. 이 매핑 정보는 페이지 테이블에 저장되며, 메모리 관리 장치가 주소 변환을 담당한다. 이를 통해 각 프로세스는 연속된 독립적인 주소 공간을 가지는 것처럼 인식하면서도, 실제 물리 메모리는 효율적으로 공유되고 관리될 수 있다.
주소 바인딩 방식은 시스템의 메모리 관리 정책과 성능에 직접적인 영향을 미친다. 실행 시간 바인딩은 메모리 단편화를 줄이고 다중 프로그래밍의 효율을 높이는 유연성을 제공하지만, 주소 변환을 위한 하드웨어 오버헤드가 발생한다. 따라서 시스템의 요구사항에 따라 적절한 바인딩 시점과 기법이 선택된다.
6.2. 메모리 맵
6.2. 메모리 맵
메모리 맵은 컴퓨터 시스템의 물리적 또는 논리적 메모리 공간이 어떻게 구성되고 할당되는지를 정의한 청사진이다. 이는 CPU가 접근할 수 있는 모든 메모리 주소 공간을, 어떤 주소 범위가 어떤 하드웨어 자원이나 기능에 매핑되는지를 명시함으로써 시스템의 메모리 자원을 체계적으로 관리하는 데 필수적이다.
일반적으로 메모리 맵은 운영체제나 펌웨어에 의해 정의되며, 주로 주기억장치인 RAM의 특정 영역과 ROM에 저장된 BIOS 또는 UEFI 펌웨어, 그리고 입출력 장치의 레지스터에 할당된 메모리 공간을 포함한다. 예를 들어, 시스템 부팅에 필요한 코드는 낮은 주소 영역에, 그래픽 처리 장치의 프레임 버퍼는 높은 주소 영역에 매핑되는 식이다.
이러한 매핑은 주소 버스를 통해 이루어진다. CPU가 특정 메모리 주소에 접근하려고 할 때, 메모리 관리 장치는 해당 주소가 실제 RAM을 가리키는지, 아니면 입출력 장치의 레지스터와 같은 메모리 맵 입출력 공간을 가리키는지를 해석하여 적절한 하드웨어로 요청을 전달한다. 이 과정은 주소 바인딩의 한 형태로, 시스템의 안정성과 하드웨어 간 효율적인 통신을 보장한다.
따라서 메모리 맵은 하드웨어와 소프트웨어가 메모리 공간을 공유하고 조화롭게 작동할 수 있도록 하는 근간이 된다. 이는 임베디드 시스템 개발이나 운영체제 커널 설계에서 특히 중요하게 다루어지며, 잘못된 메모리 맵 설정은 시스템 충돌이나 하드웨어 오동작을 초래할 수 있다.
6.3. 메모리 접근 시간
6.3. 메모리 접근 시간
메모리 접근 시간은 프로세서가 메모리에 저장된 데이터나 명령어를 요청한 시점부터 실제로 데이터를 읽거나 쓰는 작업이 완료되는 시점까지 걸리는 시간을 의미한다. 이는 컴퓨터 시스템의 전반적인 성능을 결정하는 핵심 요소 중 하나이다. 접근 시간이 짧을수록 프로세서가 데이터를 빠르게 처리할 수 있어 시스템의 처리 속도가 향상된다. 메모리 접근 시간은 일반적으로 나노초(ns) 단위로 측정된다.
메모리 계층 구조의 각 단계마다 접근 시간에 현격한 차이가 존재한다. 가장 빠른 레지스터와 캐시 메모리는 수 나노초 이내의 매우 짧은 접근 시간을 가지며, 프로세서 코어와 가장 가깝게 위치하여 고속 연산을 지원한다. 주기억장치(RAM)의 접근 시간은 수십에서 수백 나노초 정도로 상대적으로 느리다. 가장 느린 보조기억장치(HDD, SSD)의 접근 시간은 밀리초(ms) 단위로, 주기억장치보다 수천 배 이상 길다. 이러한 속도 차이를 완화하기 위해 자주 사용되는 데이터는 더 빠른 계층의 메모리에 저장하는 지역성 원리가 활용된다.
메모리 접근 시간을 구성하는 요소로는 대기 시간(Latency)과 대역폭(Bandwidth)이 있다. 대기 시간은 요청부터 첫 번째 데이터가 도달할 때까지 걸리는 시간을 말하며, 대역폭은 단위 시간당 전송할 수 있는 데이터의 총량을 의미한다. 고성능 컴퓨팅에서는 낮은 대기 시간과 높은 대역폭을 모두 확보하는 것이 중요하다. 운영체제의 메모리 관리 기법과 하드웨어 설계는 이러한 접근 시간을 최적화하여 시스템 효율을 높이는 데 기여한다.
