컴퓨터에서의 메모리(Memory)는 데이터를 저장하기 위한 하드웨어 장치이다.
인간도 중요한 행위를 위해 기억이 필요하듯이 컴퓨터도 데이터들을 기억할 필요가 있다.
메모리의 계층 구조
메모리는 속도, 용량, 비용 등의 다양한 팩터에 의해 계층적으로 구성되어 있다.
빠르고 용량이 크다는 두 마리 토끼를 모두 잡을 수 없기 때문에 특성에 따라 계층으로 구분된 것이다.
1. 레지스터 (Register)
CPU 내부에 위치한 가장 빠른 메모리.
연산에 직접 사용되는 데이터와 명령어들이 저장된다.
용량은 매우 작으나, 속도는 가장 빠르다.
2. 캐시 (Cache)
CPU와 주기억장치(보통 RAM) 사이에 위치한 메모리.
주기억장치와 레지스터 간의 속도 차이가 매우 크기 때문에, 그 중간의 스펙을 가지는 메모리를 둔 것.
L1, L2, L3의 계층으로 구분돼 있으며, 자주 사용되는 데이터 등이 캐시에 저장된다.
3. 주기억장치 (Main Memory)
우리가 흔히 RAM이라고 부르는 이 초록색 판떼기들이 주기억장치이다.
현재 실행 중인 프로그램에 관한 데이터들이 저장된다.
이 위까지 전부 전원 공급이 끊기면 데이터를 잃는 휘발성 메모리(Volatile Memory)이다.
컴퓨터의 주요 작업 공간으로써 사용된다.
4. 보조기억장치 (Secondary Memory)
HDD나 SSD가 보조기억장치의 범주에 포함된다.
이들은 비활성메모리로 데이터를 장기간 저장하기 위해 사용된다.
보통 여기에 운영체제나 우리의 소중한 파일들을 저장하게 된다.
ROM (Read-Only Memory)도 보조기억장치 중 하나라고 볼 수 있다.
메인보드에 필요한 데이터가 미리 담겨 온보드 상태로 제공된다.
5. 외부기억장치
요즘 친구들은 저장 아이콘이 왜 그렇게 생겼는지 꿈에도 모르겠지.
CD, DVD, 테이프 등이 이에 해당된다.
데이터의 영구적인 저장 및 물리적 보관을 위해 주로 사용된다.
요즘엔 거의 자취를 감춘 추억의 물건이기도 하다.
주소 공간 (Address Space)
주소 공간은 컴퓨터에서 프로세스나 프로그램이 접근할 수 있는 모든 메모리 주소의 집합을 의미한다.
이는 컴퓨터의 메모리 관리와 직접적인 연관이 있으며, 하드 및 소프트웨어 모두에게 중요하다.
1. 프로세스 메모리 구조
그전에 각 프로세스의 메모리 구조에 대해 알아보자.
프로세스는 위 이미지와 같은 형태로 데이터들을 갖고 있다.
크게 4개 영역으로 나눌 수 있다.
- 텍스트 영역
- 프로그램의 실행을 위한 코드가 저장되는 영역. - 데이터 영역
- 이미지의 GVAR와 BASS가 차지하는 영역.
- 전역변수 및 정적(Static) 변수가 저장된다. - 힙 영역
- 동적 메모리 할당을 위한 영역이다.
- 우리가 필요한 데이터를 갖고 와 메모리에 저장한다면 힙에 들어가게 된다. - 스택 영역
- 함수의 호출이나 지역 변수를 관리하는 영역이다.
- 용량이 크지 않다.
- 스택 프레임으로 구성돼 있으며, 호출 순서에 따라 데이터가 쌓인다.
- 재귀 호출 시 콜스택이 스택에 지나치게 많이 쌓이면 Stack Overflow가 발생하게 된다.
Javascript 소스코드를 통해 알아보자.
텍스트
function add(a, b) {
return a + b;
}
``add()`` 함수가 텍스트 영역에 저장된다.
데이터
// 전역 변수
const GLOBAL_VAR = 10;
// 정적 변수
static staicVar = 20;
function multiply(factor) {
return GLOBAL_VAR * factor;
}
전역변수 및 정적 변수가 데이터 영역에 저장되고, 프로그램 종료 시까지 유지된다.
힙
// 객체 생성
let foo = {
name: 'foobar',
age: 30,
};
// 배열 생성
let bar = [1, 2, 3, 4, 5];
// 함수 표현식
let func = function (x) {
return x * x;
};
``foo``, ``bar``, ``func`` 모두 동적으로 런타임에서 동적으로 할당된 메모리이기 때문에 힙 영역에 저장된다.
스택
function factorial(n) {
if (n <= 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
let result = factorial(5);
``factorial()`` 함수는 재귀적으로 호출되며 그 프레임이 스택에 계속 쌓인다.
``n``이라는 파라미터도 스택에 저장된다.
계속 호출이 일어나는데 리턴되지 못한다면 프레임이 계속 쌓여 Stack Overflow를 일으킬 수 있다.
2. 주소 공간의 종류
A. 물리적 주소 공간 (Physical Address Space)
하드웨어(RAM)를 통해 제공되는 실제 메모리 주소의 범위를 의미한다.
CPU가 메모리에 접근할 때 사용하는 주소이다.
전체 시스템에서 이를 공유하게 된다.
시스템에 설치된 물리 메모리의 용량에 제한된다.
B. 가상 주소 공간 (Virtual Address Space)
각 프로세스마다 독립적으로 할당되는 가상의 주소 공간이다.
프로세스의 주소 공간은 격리되므로 일반적으론 상호 간 접근이 제한된다.
가상 메모리를 통해 보조기억장치의 공간을 끌어와 물리 메모리보다 더 큰 용량을 사용하기도 한다.
아파트를 생각해 보자.
같은 동 안에 있는 모든 세대는 같은 구조를 공유한다. <- 물리적으로 정해져 있다.
하지만 사람(프로세스)마다 그 공간을 채우는 방식이 다르다. <- 각 프로세스가 자신만의 데이터를 채운다.
때론 불법 증축(...)을 통해 공간을 넓히기도 한다 <- 보조기억장치에서 공간을 떼온다.
이런 식으로 비유할 수 있을 것 같다.
물리적 주소 공간과 가상 주소 공간이 어떻게 매핑되는지 표현한 이미지이다.
물리 메모리의 여러 영역을 가져와 프로세스는 자신만의 주소를 부여해 관리하게 된다.
3. 주소 공간의 역할
A. 메모리 보호
가상의 주소 공간을 사용함으로써 프로세스 간의 메모리 침범을 방지한다.
따라서 시스템의 안정성과 보안을 제고할 수 있다.
영역을 구분하는 것이 서브네팅과 유사하다고 볼 수 있다.
B. 메모리 효율성
가상 메모리를 통한 물리적 한계를 넘는 큰 주소 공간을 통해 효율적인 메모리 사용이 가능하다.
필요한 영역만 물리 메모리에 할당하게 되므로 공간 사용을 최적화할 수 있다.
4. 주소 공간과 운영체제
OS는 주소 공간을 관리하고, 프로세스의 메모리 요구에 대응하기 위해 여러 작업을 담당한다.
A. 메모리 할당 및 해제
프로세스가 요구하는 만큼 메모리를 할당하고, 사용이 끝나면 회수한다.
B. 주소 매핑
가상 주소를 물리 메모리 주소로 변환하여 프로세스가 접근할 수 있게 한다.
C. 페이지 교체
물리 메모리가 부족할 경우에 대비해 페이징을 통한 효율적인 메모리 사용을 제공한다.
페이징
프로세스를 메모리에 어떻게 올릴까?
그냥 그 전체 블록을 메모리에 올려서 쓰면 될까?
1. 연속 메모리 관리의 문제
연속 메모리 관리는 각 프로세스에 메모리 공간을 연속적인 블록으로 할당하는 방식이다.
만들기는 쉽지만 다음과 같은 문제들이 있다.
A. 내부 단편화
각 프로세스에 연속된 20KB의 공간을 할당해 줬다고 하자.
만약 프로세스의 크기가 그 공간보다 작다면, 그 나머지 공간은 낭비되는 공간이 되는 것이다.
이를 내부 단편화라고 한다.
그리고 공간이 더 필요하더라도 가상 메모리를 끌고 올 수도 없다.
B. 외부 단편화
만약 프로세스 B와 D가 완료가 되어 메모리에서 할당이 해제됐다.
그럼 메모리엔 총 34KB의 공간이 남아있다.
따라서 34KB의 프로그램을 올리려고 했지만, 그 영역이 연속적이지 않아 할당에 실패했다.
이를 외부 단편화라고 한다.
이러한 현상을 최대한 줄이기 위해 비연속 메모리 관리 기법 페이징과 가상 메모리 개념이 등장하게 된 것이다.
2. 페이징
페이징이란 프로세스를 미리 정의된 크기의 페이지로 분할해 메모리에 올리는 방식이다.
여기서 페이지와 물리 메모리 관계를 매핑할 필요가 있는데, 이는 MMU(Memory Management Unit)가 수행한다.
따라서 연속하게 메모리에 할당할 필요가 없어 외부 단편화 문제를 해결할 수 있다.
하지만 내부 단편화는 여전히 발생할 수 있다.
여러 개의 프로세스가 있는 환경에서 페이징이 어떻게 구성되는지 위 이미지를 통해 쉽게 이해할 수 있다.
모든 프로세스는 각각의 페이지 테이블이 있다.
이 테이블이 각 프로세스의 페이지 영역과 물리 메모리 상의 프레임을 연결해 영역에 접근할 수 있도록 한다.
페이징의 장점
- 비교적 구현이 용이함
- 메모리를 고정 크기(페이지의 크기)로 분할해 넣어두는 것일 뿐임. - 높은 이식성
- 다른 시스템에서도 페이징 기법을 똑같이 구현할 수 있다.
- 페이지 크기도 그때그때 다르게 설정할 수 있다. - 효율적인 메모리 활용
- 외부 단편화가 없음.
- 내부 단편화가 존재는 하나 오버헤드를 초래할 정도는 아님.
- x86-64 시스템의 기본 페이지 크기는 4KB.
- 요즘의 프로그램은 크기가 크므로 4KB의 크기로 충분히 단편화 없이 활용 가능.
결론
컴퓨터에서 메모리와 주소 공간은 데이터 관리 및 프로그램 실행에서 매우 중요한 위치를 차지하고 있다.
시스템의 성능 및 보안에 직결되는 만큼 그 중요도는 말하면 입만 아플 것이다.
메모리에 대해 잘 이해해야 프로그래머로서의 기본을 갖추었다고 볼 수 있겠다.
Reference
[운영체제] 9. 페이징 메모리 관리 <- 매우 상세함 ! ! !
'Camp > Standard' 카테고리의 다른 글
프로세스와 스레드 (0) | 2024.10.31 |
---|---|
컴퓨터에서의 CPU란? (0) | 2024.10.07 |
[OSI 7계층] 응용 계층 (0) | 2024.09.23 |
[OSI 7계층] 전송 계층 (0) | 2024.09.06 |
[OSI 7계층] 네트워크 계층 (0) | 2024.09.06 |