흔히 RAM(Random Access Memory)를 말하며 주기억장치 라고도 불린다.
- 프로그램이 실행되는 동안 필요한 정보를 저장하는 기억장치
책상
에 많이 비유하곤 합니다.
- SRAM은 각 비트를 이중안정(bistable) 메모리 셀에 저장한다. 이중안정 본성으로 인해 SRAM 메모리 셀은 자신의 값을 전원이 공급되는 한 유지한다.
- SRAM은 DRAM과 달리 refresh가 필요 없고, 외란에 민감하지 않다. 대신 DRAM보다 트랜지스터를 더 많이 사용하며 더 낮은 밀도를 가지고 더 비싸고 더 많은 전력을 소모한다
- ex) 캐시메모리
DRAM은 주기적으로 메모리의 모든 비트를 읽었다가 다시 써 주는 방식으로 refresh해야 한다. 또한 DRAM은 빛이나 전기적 잡음 같은 외란에 민감하다.
- ex) 메인메모리, 그래픽 시스템의 프레임 버퍼
- 코드 : 실행할 프로그램의 코드가 저장되는 텍스트 영역이다. CPU는 코드영역에서 저장된 명령어를 하나씩 가져가서 처리한다.
- 데이터 : 전역변수와 정적변수가 이해 해당된다. 프로그램의 시작과 함께 할당되며 프로그램이 종료되면 소멸된다.
- 스택 : 스택영역은 함수의 호출과 관계되는 지역변수와 매개변수가 저장되는 영역이다.
함수의 호출과 함께 할당되며, 함수의 호출이 종료될때 해제된다.- 힙 : 힙 영역은 사용자가 직접 관리할 수 있는 메모리 영역이다. 힙 영역은 사용자에 의해 메모리공간이 동적으로 할당되고 해제된다.
- 프로세스마다 독립적으로 가지는 주소 공간
- 각 프로세스마다 0번지부터 시작
- CPU가 보는 주소
- 메모리에 실제로 올라가는 위치
- 주소를 결정하는 것.
- Symbolic Address ->
"Logical Address -> Physical Address"
의 과정에서 결정
Symbolic Address
- 변수 이름, 함수 이름과 같이 프로그래머가 사용하는 주소
ex) int * a=&n;
- 물리적 주소가 컴파일 시 결정됨
- 고정된 주소를 사용하기 때문에 프로세스의 시작 위치 변경되면 재컴파일 해야한다
- 컴파일러는 절대 주소(absolute address) 생성
논리적 주소와 물리적 주소가 동일함
- Loader가 프로세스를 메모리에 load 하는 시점에 물리적 주소를 결정
- 메모리상에 비어있는 위치에 언제든 올라갈 수 있도록 컴파일러가 재배치가능코드(relocatable code)를 생성해야 한다.
- 프로세스가 실행될 때 메모리 주소를 바꾸는 방법 즉, Runtime때 물리적 주소가 결정되며 실행 도중에
주소가 바뀔 수 있다.- CPU가 주소를 참조할 때마다 address mapping table을 이용하여 binding을 점검한다
- 하드웨어적인 지원이 필요하다
- ex) base and limit registers, MMU(Memory Management Unit)
- MMU는 논리적 주소를 물리적 주소로 매핑해주는 역할을 하며 논리적 주소에 base register의 값을 더하는 방식이다.
- base register는 하나이며 프로세스끼리 공유한다.
접근할 수 있는 물리적 주소의 최솟값을 나타낸다
논리적 주소의 최댓값이며, 프로그램 크기를 담고있다.
잘못된 메모리를 참조하지 않도록 막아주는 기능을 한다.
만약 커널모드인 경우에는 MMU가 논리적 주소를 그대로 사용한다. 따라서 커널 모드인지 체크하는 과정이 포함되어 있다.
프로세스를 일시적으로 메모리에서 backing store(swap area, 디스크)로 쫓아내는 것.
- 일반적으로 중기 스케줄러(swapper)에 의해 swap out 시킬 프로세스를 결정한다. 우선순위가 낮은 프로세스는
swap out 시켜 디스크로 보내고 우선순위가 높은 프로세스를 메모리에 load 한다.- swap in 될 때 compile time, load time 방식은 원래 메모리 위치로 load해야 한다.
- execution time 에서는 빈 메모리 영역 아무 곳에나 load할 수 있다.
- swap time은 swap되는 양에 비례하다.
- 커널영역
- interrupt vetor와 함께 낮은 주소 영역 사용
- 사용자 프로세스 영역
말 그대로 프로세스들을 메모리에 연속적으로 할당시키는 방법이다.
Fixed partition allocation(고정 분할)
- 메모리의 공간을 고정된 크기로 나누는 방식
- 분할의 크기는 모두 동일하거나 다를 수 있고 동시에 메모리에 load되는 프로세스 개수가 고정되며 수행
가능한 프로세서의 크기가 제한된다.internal fragmentation, external fragmentation 발생
Variable partition allocation(가변 분할)- 프로세스의 크기를 고려해서 할당하는 방식
- 분할의 크기나 개수가 동적으로 변한다
- 기술적 관리 기법이 필요하다.
external fragmentation 발생
가변 분할 방식에서 크기가 n인 프로세스가 들어갈 가장 적절한 hole을 찾는 문제로 3가지 방식이 있다.
Hole
- 가용 메모리 공간
- 다양한 크기의 hole들이 메모리 여러 곳에 흩어져 있다.
- 프로세스가 도착하면 수용 가능한 hole을 할당
- 운영체제는 다음의 정보를 유지해야 한다.
- 할당공간
- 가용공간(hole)
external fragmentation 문제를 해결하는 한 가지 방법으로 사용중인 메모리 영역을 한군데로 몰아넣고
hole들을 다른 한 곳으로 몰아 큰 hole을 만드는 것이다.
- 매우 높은 cost가 발생하며 최소한의 메모리 이동으로 compaction하는 방법이 매우 복잡하다.
- 프로세스의 주소가 실행 시간에 동적으로 재배치 가능한 경우에만 수행 가능하다.
프로그램을 의미 단위인 여러개의 segment 단위로 구성하는 방법
- 작게는 프로그램을 구성하는 함수 하나하나를 세그먼트로 정의
- 크게는 프로그램 전체를 하나의 세그먼트로 정의가 가능하다.
- 일반적으로는 code, data, stack 부분이 하나씩의 세그먼트로 정의됨
- 세그먼트 테이블을 이용해 주소변환
<segment-number, offset>
각각의 테이블은 다음 두 가지를 가진다
- base: 세그먼트의 시작 물리적 주소
- limit: 세그먼트의 길이
Segmentation의 장점은 paging과 마찬가지로 segment들이 연속적으로 할당될 필요가 없고, stack과 heap이 독립적으로 커질 수 있으며, segment마다 protection을 따로 수행할 수 있는 등 paging과 유사한 장점을 가지고있다. 하지만, 각각의 segment는 반드시 연속적으로 할당해야 하는 단점이 있다.
프로그램의 실행 속도와 효율성
때문입니다. 하지만 가상메모리나 페이지 매핑으로 물리적 메모리가 연속적일 필요는 없지만 논리적인 연속성은 항상 유지되어야 메모리 관리가 간소화되고 성능이 보장됩니다.각 세그먼트 별로 엔트리(Entry)에는 정보를 담고 있는 bit가 포함되어 있다
- Valid-invalid bit: valid는 해당 주소의 세그먼트에 그 프로세스를 구성하는 유효한 내용이 있음.
invalid는 없음(접근 불가)- Protection bit: 세그먼트에 대한 Read/Write/Execution 권한
segment를 공유할 수 있다.
- 같은 segment 번호를 사용해야함
- segment는 의미 단위이기 대문에 공유와 보안에 있어서 paging보다 훨씬 효과적이다.
fitst-fit / best-fit 을 사용하기 때문에 외부 단편화(external fragmentation)가 발생한다.
- segment의 길이가 동일하지 않으므로 가변분할 방식에서와 동일한 문제점들이 발생함
프로세스가 순서대로 메모리에 저장되지 않기 때문에 프로세스를 실행하기 위해선 page가 어느 frame에 들어있는지를 알아야 하기 때문에 이에 대한 정보가 page table이라는 테이블에 저장되어 있고, 이를 사용하여 논리적 주소를 물리적 주소로 mapping 한다.
page number, page offset
page number는 page table의 인덱스로써 page table에 접근할 때 사용된다.
page offset은 물리적 주소를 얻을 때 사용되고 page table의 abse address에 page offset을 더하면 물리적 주소를 구할 수 있다.
page table은 메인 메모리에 저장하고 PTBR(Page-Table Base Register)라는 레지스터가 page table을 가리키도록 한다.
page table의 각 엔트리(Entry)에는 정보를 담고 있는 bit가 포함되어 있다.
- Protection bit: page에 대한 접근 권한 Read/Write/Read-only
- Vaild-invalid bit: vaild는 해당 주소의 frame에 그 프로세스를 구성하는 내용이 있다. invaild는 없음(접근 불가)
page의 크기가 작아질수록 내부 단편화가 감소하고 필요한 정보만 메모리에 load 할 수 있어 효율적이지만, page table의 크기가 증가하고 디스크 이동의 효율성이 감소한다.
TLB hit 비율을 a라고 하고, TLB를 탐색하는데 걸리는 시간을 b라고 하면, 메모리 접근 횟수의 기댓값은
TLB hit + TLB miss = (b+1)a + (b+2)(1-a) = 2+b-a가 된다.
- 매 Switch마다 TLB 전체를 비우는 방법이 있지만 캐시를 flush 하기 때문에 cost가 높다.
- TLB의 각 엔트리가 어느 프로세스를 위한 것인지 추적하여 이용되지 않는 엔트리만 비운다. 이를 ASID를 이용하여 해결한다.
ASID는 Process ID와 유사하지만 8bit로, 32bit인 PID보다 가볍다. 동일한 ASID를 갖는 프로세스끼리는 TLB를 공유할 수 있기 때문에, 이런 경우엔 TLB를 비우는 오버헤드를 줄일 수 있다.