Search

메모리 (인프런 강의)

메모리 종류

위의 그림은 컴퓨터에서 사용되는 메모리들
오른쪽으로 갈수록 가격은 싸지고 용량은 커지지만 속도는 느려진다

레지스터

가장 빠른 기억장소, CPU 내에 존재
CPU가 사용하는 메모리로 굉장히 빠름
컴퓨터가 전원이 꺼지면 데이터가 사라지기 때문에 휘발성 메모리라고 부름
CPU를 구분할 때 32비트, 64비트 → 레지스터의 크기
32비트 레지스터 → 32bit CPU
CPU는 계산을 할 때 메인메모리에 있는 값을 레지스터로 가져와 계산을 한다.
계산 결과는 다시 메인메모리에 저장시킨다
왼쪽 : 명령어 오른쪽: 데이터
어셈블리 코드를 보는 이유
기계어로 일대일 매칭이 되기 때문에 실제로 레지스터를 사용하는 것을 볼 수 있기 때문
정확히 무슨 일을 하는지는 알 수 없지만 레지스터를 가지고 무언가 처리를 한다.

캐시

휘발성 메모리
레지스터와 메인메모리 사이 존재
메인메모리는 너무나 느리고 레지스터는 엄청 빠르다
메인 메모리에 있는 값을 레지스터로 옮기려면 한참 걸리기 때문에 미리 가져온다
미리 가져온 데이터를 저장하는 곳이 바로 캐시
캐시는 성능의 이유로 여러 개를 둔다
CPU가 값을 요청해 레지스터로 값을 옮겨야 한다면 단계에 따라 가장 속도가 빠른 L1 캐시를 보고 여기에 없다면 L2캐시를 확인해보고 여기도 없다면 메인 메모리에서 값을 가져온다

메인 메모리

프로그램이 실제로 올라갈 메인 메모리
실제 운영체제와 다른 프로세스들이 올라가는 공간
전원이 공급되지 않으면 데이터가 지워지기 때문에 휘발성 메모리
하드디스크나 SSD보다 속도는 빠르지만 가격이 비싸기 때문에 데이터를 저장하기 보다는 실행 중인 프로그램만 올린다

보조저장장치(하드디스크, SSD)

이전에 살펴본 메모리들은 휘발성 메모리에 가격이 비싸서 오래 저장할 파일을 저장하기 어려웠다.
가격이 저렴하고 전원이 공급되지 않아도 데이터가 지워지지 않는 비휘발성 메모리를 만들었다.
캐시와 레지스터와 같은 메모리로는 큰 용량을 만들려면 비용이 너무 크다.

메모리와 주소

오늘날 컴퓨터는 폰 노이만 구조로 되어 있음
폰 노이만 구조는 모든 프로그램을 메모리에 올려 실행시킨다
유니 프로그래밍 환경에서는 하나의 프로그램만 메모리에 올라오기 때문에 메모리 관리가 어렵지는 않았으나
멀티 프로그래밍 환경에서는 여러 프로세스가 올라오니 복잡하고 어려워짐
운영체제는 메모리를 관리하기 위해서 1바이트(8bit) 크기로 구역을 나누고 숫자를 매긴다
이 숫자는 주소 라고 불린다

32 bit CPU와 64bit CPU

32bit CPU
레지스터 크기가 32bit
CPU가 처리하는 ALU(산술논리연산장치) = 32bit
데이터가 이동하는 BUS도 32bit
CPU가 다룰 수 있는 메모리도 2322^{32}으로 4GB
64bit CPU
레지스터 크기, ALU, 버스의 크기 = 64bit
다룰 수 있는 메모리의 크기 2642^{64} → 무한대에 가까움
32bit CPU보다 한번에 처리할 수 있는 양이 많기 때문에 속도가 더 빠르다

물리 주소와 논리 주소

물리 주소
메모리를 컴퓨터에 연결하면 0X0 번지 부터 시작하는 주소 공간
논리 주소
사용자 입장에서 바라본 주소 공간
사용자는 물리 주소를 몰라도 논리 주소로 물리 주소에 접근할 수 있다
메모리에는 운영체제와 수 많은 프로세스가 올라온다
그 중, 운영체제는 특별하기 때문에 운영체제를 위한 공간은 따로 마련해둡니다
사용자가 악의적인 프로그램을 만들어 사용자 프로세스가 운영체제를 침범하면 굉장히 위험할 수 있다
하드웨어적으로 운영체제 공간과 사용자 공간을 나누는 경계 레지스터를 만들었음
경계 레지스터
CPU 내에 존재하는 레지스터로 메모리 관리자(Memory Management Unit)가 사용자 프로세스가 경계 레지스터의 값을 벗어났는지 검사하고 만약 벗어났다면 그 프로세스를 종료시킨다

절대 주소와 상대 주소

개발자는 개발을 할 때 프로그램이 실행될 주소를 신경쓰지 않고 개발을 한다
이는 컴파일러가 컴파일을 할 때, 메모리 0번지에서 실행한다고 “가정”하기 때문.
개발자의 프로그램을 실행시켜 메모리의 사용자 공간 0x4000번지에 올라왔다고 가정
컴파일러는 0x0번지라고 가정해서 프로그램을 만들었고 이는 상대주소이다
실제 프로그램이 올라간 주소는 0x4000번지이지만 이는 메모리 관리자가 바라본 “절대 주소”이다.
정리하자면 사용자가 바라본 주소인 “상대 주소” 는 논리 주소 공간 이라고 불리고
메모리 관리자가 바라본 절대 주소는 물리주소 공간
1.
사용자가 0x100번지(상대주소, 논리주소)에 있는 데이터를 요청
2.
CPU는 메모리 관리자(MMU)에게 100번지에 있는 데이터를 가져오라고 한다
3.
메모리 관리자는 CPU가 요청한 0x100번지와 재배치 레지스터에 있는 0x4000번지의 값을 더한 0x4100번지(절대 주소, 물리 주소)에 접근해서 데이터를 가지고 온다
4.
재배치 레지스터에는 프로그램의 시작 주소가 저장되어 있다
5.
메모리 관리자는 사용자가 메모리에 접근할 때마다 이렇게 계산을 수행
메모리 관리자 덕분에 모든 사용자 프로세스는 0x0번지부터 시작한다는 가정으로 편하게 프로그램을 만들 수 있고 만약 시작 영역이 바뀌더라도 재배치 레지스터만 변경해주면 되기 때문에 굉장히 유연

메모리 할당 방식

메모리 오버레이(memory overlay)
유니 프로그래밍 환경에서 메모리보다 더 큰 프로그램을 실행 시키는 방법
⇒ 큰 프로그램을 메모리에 올릴 수 있도록 잘라서 당장 실행시켜야 할 부분만 메모리에 올리고
⇒ 나머지는 용량이 큰 하드 디스크에 저장하는 기법
큰 프로그램을 작게 나누어 일부만 실행하고 일부는 하드디스크에 저장
이 때 하드디스크의 스왑 영역이라는 곳에 저장이 된다
만약 메모리에 1gb를 올리고 스왑영역에 8gb를 올려서 실행한다고 하면 사용자는 메모리가 9gb인 것처럼 느끼게 됨
스왑 : 스왑 영역에 있는 데이터 일부를 메모리로 가져오고 메모리에 있는 데이터를 스왑 영역으로 옮기는 것
하지만 스왑 과정이 존재하기 때문에 실제 메모리가 9gb인 컴퓨터보다는 느리게 동작
그렇다면 오늘 날과 같이 메모리에 여러 개의 프로세스가 올라오는 멀티 프로그래밍 환경에서는 메모리 관리를 어떻게 할까..?
메모리를 어떻게 나눌까… 2가지 방식으로 나누기로 함
1.
가변 분할 방식
프로세스의 크기에 따라 메모리를 나누는 방식
위와 같이 한 프로세스가 메모리 안 연속된 공간에 할당되기 때문에 연속 메모리 할당이라고 한다.
2.
고정 분할 방식
프로세스의 크기와 상관없이 메모리를 정해진 크기로 나누는 방식
한 프로세스가 메모리에 분산되어 할당 ⇒ 비연속 메모리 할당
2mb 고정 분할
프로세스 A가 여러개로 쪼개져서 여러 곳에 할당됨
5mb 프로세스 A는 2mb로 나눈 구역 3개에 나눠서 할당됨 ⇒ 1mb 낭비 공간이 발생
프로세스 B는 정확히 맞고 프로세스 C는 낭비 공간 1mb가 생김
3.
가변 분할 방식과 고정 분할 방식의 장단점
a.
가변 분할 방식
i.
장점
메모리에 연속된 공간에 할당되기 때문에 더 크게 할당돼서 낭비되는 공간인 내부 단편화 가 발생하지 않음 → 프로세스 크기에 딱 맞게 할당이 된다
ii.
단점
외부 단편화 발생
b.
고정 분할 방식
i.
장점
구현이 간단, 오버헤드가 적음 (같은 크기로 나누기 때문에 단순)
ii.
단점
작은 프로세스도 큰 영역에 할당돼서 공간이 낭비되는 내부 단편화 발생
c.
오늘 날의 운영체제는 가변분할 방식과 고정 분할 방식을 혼합하여 단점을 줄임
외부 단편화
가변 분할 방식에서 발생
가상 메모리 시스템에서는 가변 분할 방식을 세그멘테이션 이라고 부름
프로세스 A와 D가 작업을 마치고 나가면 해당 공간이 빈 공간이 된다
둘이 합치면 60MB이지만 새로운 프로세스(60mb)가 들어가려고 해도 연속된 공간이 아니어서 새로운 프로세스에게 메모리를 할당할 수 없다 ⇒ 외부 단편화 발생
외부 단편화가 발생한 공간을 합쳐주는 조각 모음을 하면 된다
하지만 조각모음을 하려면 현재 메모리에서 실행되고 있는 프로세스들의 작업을 일시 중지하고 메모리 공간을 이동시키는 작업을 해야하기 때문에 오버헤드가 발생
내부 단편화
고정 분할 방식에서 발생
가상 메모리 시스템에서 고정 분할 방식을 페이징 이라고 한다
책의 페이지처럼 크기가 정해져 있다고 해서 붙은 이름
20MB로 메모리를 분리
메모리가 부족하기 때문에 프로세스 A의 나머지 10MB는 하드 디스크 내 스왑 영역에 할당
프로세스 C와 D의 크기는 분할된 크기보다 작기 때문에 내부에 빈 공간이 생겨서 낭비됩니다 ⇒ 내부 단편화
분할되는 크기를 조절해서 내부 단편화를 최소화한다 (해결방안은 아니다)
버디 시스템
가변 분할 방식과 고정 분할 방식을 혼합 → 단점 최소화
2의 승수로 메모리를 분할하여 메모리를 할당
근접한 메모리 공간을 합치기 쉽다 → 2의 승수로 나눴기 때문에 반대로 조립만 하면 됨