메모리 종류
- 컴퓨터 내부의 메모리들
레지스터(Register)
: 가장 빠른 기억 장소
- CPU 내에 존재
- CPU는 계산을 할 때, 메인 메모리에 있는 값을 레지스터로 가져와 계산함
→ 계산 결과는 다시 메인 메모리에 저장함
- CPU는 계산을 할 때, 메인 메모리에 있는 값을 레지스터로 가져와 계산함
- 휘발성 메모리 ⇒ 컴퓨터 전원이 꺼지면 데이터가 사라짐
- 32비트 CPU는 레지스터 크기가 32비트, 64비트 CPU는 64비트임
캐시(Cache)
: CPU와 메모리 간 속도 차이를 줄이기 위한 메모리
- 레지스터는 CPU가 사용하는 메모리로 굉장히 빠르지만 그에 비해 메인 메모리는 느림
→ 메인 메모리에 있는 값을 레지스터로 옮기려면 한참 걸리기 때문에 필요할 것 같은 데이터를 미리 가져와서 저장함
⇒ 캐시 메모리 - 휘발성 메모리 ⇒ 컴퓨터 전원이 꺼지면 데이터가 사라짐
- ex) CPU가 값을 요청해서 값을 레지스터로 옮겨야 한다면
→ 단계에 따라 가장 속도가 빠른 L1 캐시를 보고, 없다면 L2 캐시를 확인해보고, 여기에도 없다면 메인 메모리에서 값을 가져옴
메인 메모리(RAM)
: 실제 운영체제와 프로세스들이 올라가는 공간
- 휘발성 메모리 ⇒ 컴퓨터 전원이 꺼지면 데이터가 사라짐
- 보조 저장 장치(하드 디스크, SSD)보다 속도는 빠르지만 가격이 비싸기 때문에 데이터를 저장하기보다는 실행 중인 프로그램을 올리는 데 사용됨
보조 저장 장치(하드 디스크, SSD)
: 데이터를 장기 저장하는 비휘발성 메모리
- 비휘발성 메모리 ⇒ 컴퓨터 전원이 꺼져도 데이터가 사라지지 않음
메모리와 주소
- 개요
- 오늘날 컴퓨터는 폰 노이만 구조로 되어 있음
→ 폰 노이만 구조는 모든 프로그램을 메모리에 올려 실행시킴 - 멀티 프로그래밍 환경에서는 메모리에 여러 프로세스가 올라와서 관리가 복잡하고 어려움
→ 운영체제는 메모리를 관리하기 위해 1바이트 크기로 구역을 나누고 숫자를 매김 → 이를 주소(address)라 부름
- 오늘날 컴퓨터는 폰 노이만 구조로 되어 있음
32비트 CPU
- 레지스터 크기, CPU가 처리하는 ALU(산술논리연산장치), 데이터가 이동하는 버스 ⇒ 32비트
- CPU가 다룰 수 있는 메모리 ⇒ 4GB (2의 32승)
64비트 CPU
- 레지스터 크기, CPU가 처리하는 ALU(산술논리연산장치), 데이터가 이동하는 버스 ⇒ 64비트
- CPU가 다룰 수 있는 메모리 ⇒ 무한대 (2의 64승)
- 64비트 CPU가 > 32비트 CPU보다 한 번에 처리할 수 있는 양이 많기 때문에 속도가 더 빠름
물리 주소와 논리 주소
물리 주소
: 실제 메모리(RAM)에서 데이터를 저장하거나 읽을 때 사용하는 실제 단일 주소
- 메모리 칩 내에 있는 특정 위치를 가리키는 ‘진짜’ 주소
- 메모리의 1000번지, 5832번지 이런 식으로 하나하나 특정 지점을 의미
- CPU가 메모리에 접근할 때는 최종적으로 이 물리 주소를 사용함
논리 주소
: 프로세스가 메모리를 사용할 때 CPU나 사용자 입장에서 보는 가상의 주소
- 프로그램은 논리 주소를 사용해서 메모리에 접근하려고 하지만, 실제 메모리 위치인 물리 주소와는 다름
- 메모리 관리자가 이 논리 주소를 물리 주소로 변환해줌
물리 주소 공간
: 실제 메모리에서 물리 주소가 가질 수 있는 전체 범위(공간)
- 메모리를 컴퓨터에 연결했을 때, 0번지부터 시작하는 주소 공간
- ex) 컴퓨터에 16GB 메모리가 있다면, 그 16GB 전체가 물리 주소 공간
⇒ 0번지부터 16GB 메모리 끝까지 모든 물리 주소들의 집합(범위)
논리 주소 공간
: 프로세스가 사용하는 논리 주소들의 전체 집합
- 사용자가 바라보는 전체 가상의 메모리 공간
- 사용자는 물리 주소를 몰라도 논리 주소로 물리 주소에 접근할 수 있음
경계 레지스터
: 운영체제와 사용자 메모리 공간을 나누는 역할
- 개요
- 메모리에는 운영체제와 여러 프로세스들이 올라감
→ 그 중에 운영체제는 특별하기 때문에 운영체제를 위한 공간을 따로 마련해둠 - 만약 악의적인 프로그램이 들어와 운영체제를 침범하면 위험하기 때문에 하드웨어적으로 운영체제 공간과 사용자 공간을 나누는 경계 레지스터를 만듦
- 메모리에는 운영체제와 여러 프로세스들이 올라감
- CPU 내에 존재하는 레지스터
- 메모리 관리자는 사용자 프로세스가 경계 레지스터의 값을 벗어났는지 검사함
→ 만약 벗어났다면 그 프로세스는 종료시킴
절대주소와 상대 주소
절대주소
: 실제 메모리 주소
- 메모리 관리자가 바라본 주소
- 물리 주소 공간
상대주소
: 프로그램이 시작된 지점을 기준으로 계산한 주소
- 사용자가 바라본 주소
- 논리 주소 공간
- 개발자는 프로그램을 만들 때, 프로그램이 실행될 주소를 신경쓰지 않고 개발함
→ 컴파일러가 컴파일을 할 때, 메모리 0번지(주소)에서 실행한다고 가정하기 때문
→ 이렇게 만들어진 주소를 상대 주소(논리 주소) 라고 함
- 개발자의 프로그램을 실행시켜 메모리의 사용자 공간 4000번지(주소)에 올라왔다고 가정했을 때
→ 컴파일러는 0번지라고 가정해서 프로그램을 만듦 ⇒ 상대 주소(사용자 관점)
→ 실제 프로그램이 올라간 주소는 4000번지임(메모리 관리자 관점) ⇒ 절대 주소(메모리 관리자 관점) - ex) 사용자가 100번지에 있는 데이터를 요청
→ CPU는 메모리 관리자에게 100번지에 있는 데이터를 가져오라고 함
→ 메모리 관리자는 CPU가 요청한 100번지와 재배치 레지스터에 있는 4000번지의 값을 더한 4100번지에 접근해서 데이터를 가져옴
- 재배치 레지스터에는 프로그램의 시작 주소가 저장되어 있음
- 메모리 관리자는 사용자가 메모리에 접근할 때마다 이렇게 계산함
메모리 할당 방식
고정 분할 메모리 할당
: 메모리를 고정된 크기로 분할하여 각 영역에 하나의 프로세스를 할당하는 방식
- 장점: 구조가 단순해서 구현이 쉬움
- 단점
- 프로세스의 크기가 < 분할된 크기보다 작으면 공간이 낭비되는 내부 단편화가 발생
- 프로세스의 크기가 > 분할된 크기보다 크면 실행 불가능
가변 분할 메모리 할당
: 메모리를 프로세스의 크기에 맞춰 유동적으로 분할하여 할당하는 방식
- 장점: 프로세스 크기에 맞게 메모리를 분할하므로 내부 단편화가 발생하지 않음
- 단점: 남은 메모리 공간의 총합은 충분하지만, 이들이 연속된 공간이 아니라서 프로세스를 실행할 수 없는 외부 단편화가 발생
연속 메모리 할당
: 고정, 가변 모두 연속된 메모리 공간을 요구함
- 고정 분할 메모리 할당과 가변 분할 메모리 할당은 연속된 메모리 공간이 없으면 프로세스를 실행할 수 없음
⇒ 이러한 특징으로 인해 두 방식은 연속 메모리 할당으로 분류됨 - 과거 운영체제에서 사용되던 방식
- 현재는 임베디드 같은 특수한 환경에서만 사용됨
내부 단편화 (Internal Fragmentation)
: 메모리를 필요보다 크게 할당해서, 사용하지 않는 공간이 낭비되는 것
- 원인: 메모리를 고정된 크기로 나눌 때 발생함
- ex) 100KB 공간에 70KB짜리 프로세스를 넣으면, 남는 30KB가 낭비됨
외부 단편화 (External Fragmentation)
: 전체 빈 공간은 충분한데, 쪼개져 있어서 연속된 큰 공간을 못 만드는 경우
- 원인: 메모리를 가변 크기로 여러 번 할당/해제하면서 공간이 산발적으로 흩어질 때 발생함
- ex) 50KB + 30KB + 20KB = 100KB의 빈 공간이 있어도, 100KB짜리 프로세스를 못 넣음
요약
- 내부 단편화: 안에서 남는 공간 낭비
- 외부 단편화: 밖에 흩어진 공간이라 통합 불가능