- 메모리는 물리적으로 어떻게 구성되나
- 메모리 주소체계
- 여러 bit를 어떤 식의 주소로 쓰나
- 페이징할 때의 주소는 어떤 형식
- 프로그램 -> 메모리로 주소가 어떻게 변환되나
- 메모리 할당
- protection memory
- 메모리를 할당하는 방법과 단편화 문제
- 페이징 시 주소변환, 효율적인 변환방법들
- 프로세스 context switching 때 페이징 관리 , demanding page보완
- 페이징 교체 알고리즘
결국 메모리에 프로그램의 정보를 어떻게 잘 서로 격리하며 저장하고 효율적으로 사용할거냐의 문제이다
키워드:
-주소
address binding, 심볼릭 주소/ relocable 주소/절대주소/ 물리주소 , mmu, 컴파일러, 링킹, 로딩
-메모리 관리
protection of memory, base register, limit register,연속적 메모리 할당 , dynamic allocation , 외부 단편화, 내부 단편화, free-frame list
-페이징
page table, tlb, valid-invalid bit, page in,
page out, dirty bit,internal table, demanding page
,pure demanding page
메모리(메인 메모리)는 ram(random access memory)이라고도 하며 디스크보다 빠른 속도의 i/o가 가능하지만 휘발되는 저장공간이다.
(주로 d-ram이 사용됨)
아래와 같이 생겼으며, 저 칩 하나하나에 몇 억 개의 셀이 존재한다.
셀은 캐패시터와 트랜지스터로 전하를 저장/제어하는 단위이다.
이 셀에 전하가 저장되있냐 아니냐로 0,1을 표현해 기계어를 저장한다.
메모리는 몇 억개의 셀의 집합이고, 이것으로 0,1을 표현하는데
어떤 셀이 어떤 데이터를 나타내는지 컴퓨터는 어떻게 인지해서 사용하는 걸까?
결론은 셀들을 byte단위로 배열처럼 열과 행으로 나눠 주소를 지정해서 사용한다. 메모리는 기본적으로 바이트(byte)단위로 cpu로 읽고 쓰는데 1byte는 8bit로, 8개의 셀에 있는 정보를 의미한다.
그렇다면 프로그램은 0x00000000 ... 0xFFFFFFFF의 물리주소를 그대로 사용할까?
결론은 아니다.
int a = 12345;
와 같은 코드가 있다고 하자. 이는 실행되기 전까지는 디스크에 저장된 일종의 .exe파일일 뿐이다. 이게 실행될 때 a라는 변수가 메모리의 어느 주소에 있는지를 할당하는 것은 정해져있지 않다.(symbolic할 뿐이다) 이를 지정은 컴파일러가 수행한다.
코드의 변수 a와 같은 symbolic한 변수를 컴파일러가 메모리에 할당가능한 가상의 주소로 바꿔서 어셈블리어로 서술하는 것이다.
이 relocable한 주소는 링커(linker) 를 통해 absolute address가 정해지고, 로더(loader)를 통해 프로세스가 물리적으로 어디부터 어디의 메모리 주소(physical address)를 사용할지 할당을 os의 커널을 통해 수행힌다.
symblic address -> relocable address -> absolute address -> physical address
즉 이 logical한 가상의 주소를 물리주소로 바꿔서 할당하고 접근하는 작업을 os가 수행하면서 주소변환,프로세스간의 메모리 보호 기능도 수행한다.
mmu(memory management unit)이라고 하는 물리적인 장치를 이용해 수행한다.
메모리 보호 기능: 프로세스가 서로 별도의 메모리 공간을 사용해야하므로 이를 위한 제약을 구현해야한다.
-> 이를 base register와 limit register를 통해 cpu에서 메모리로의 접근 범위를 제한해서 가능하게 한다.(protection of memory space)
이는 페이징을 적용하면서 페이지 테이블에 조금 다른 방식으로 구현된다.
그러면 실행파일 전체를 메모리에 로드해야 할까?
정적 링킹을 하면 여러 프로그램이 공유하는 라이브러리들이 메모리에 중복해서 올라가게된다.
더 효율적으로 실행할 수는 없을까? ->
dynamic linking으로 가능하다.
프로그램 실행 시점에 필요한 일부 라이브러리만 메모리에 적재하는 방식이다.
이 경우 shared page가 가능하다.
dll같은 공용 라이브러리들을 공유하기 좋다.
물리적으로는 공용 라이브러리를 메모리 1개만 올려놓고 링킹, 로드 시에 적절하게 주소만 연결해주면 효율적 사용이 가능하다.
메모리를 어떻게 할당해줄 거냐?
가장 무식하게는 실행파일을 메모리의 연속적인 주소에 전부 할당해버리는 방법이 있다 (contiguous memory allocation).
이려면 memory protection도 base register의 값부터 + bae+limit register의 값까지로 단순하게 구현된다.
하지만 이렇게 할 수없는 몇 가지 이유가 있다.
1) 프로세스가 메모리를 얼마나 쓸 건지는 가변적이다. -> 실행시부터 그걸 미리알고 적정한 크기를 할당하기는 힘들다.
2) 메모리 페이지네이션을 적용하면 메모리 주소들이 나눠지므로 연속적으로 할당해줄 수 없다. 프로세스는 중간에 끝나기도 하고 새로 생기기도 하면서 불규칙하게 빈 공간들(hole)이 생기는데 이를 활용하기 위해서는 연속할당을 못하고 페이지네이션을 해야한다.
홀을 최대한 활용해 부분부분의 메모리 할당으로 큰 프로세스 할당을 가능하게 하려면, 이런 외부 단편화문제(external fragmentation)를 해결해야 한다.
홀의 활용을 위해 일정한 크기로 나눠서 할당해(페이징 적용) 보완할 수도 있다. 이 경우 그 일정한 크기(각 페이지)에 대해서도 사용하지 않는 메모리 공간이 생긴다. -> 내부 단편화
demanding page , valid-invalid 비트 이용, dirty bit
internal table과 page table차이?
pure demand paging, trap, instruction restart
copy on write
페이징은 앞서 설명했듯 일정한 크기로 메모리를 나눠서 메모리 로드 시 해당 단위로 로드하는 방식이다.
페이지를 가상의 메모리 공간, 프레임을 실제 메모리에서 나눠진 공간이라 한다면 아래와 같이 필요할 때마다 페이지를 프레임에 매치시켜 관리할 수 있다.
하지만 이때 여러 이슈가 생긴다.
페이지 테이블이라는 페이지와 프레임에 대한 메타 데이터를 저장해 이를 참조해 접근한다.
프로세스의 가상 주소가 물리주소로 변환되는 과정과 함께 보자.
프로세스의 프로세스 테이블에서의 참조를 통해 PCB에 접근한다. PCB에는 해당 프로세스의 여러 정보가 담겨있는데, 이중 페이지 테이블에 대한 참조 또한 존재한다. 이렇게 페이지 테이블에 접근해서 페이지 주소와 매칭된 프레임을 찾아 물리주소로 접근한다.
즉, 프로세스 테이블 -> PCB -> 페이지 테이블의 흐름으로 접근한다.
페이지 테이블을 메인 메모리에 아닌 더 빠른 메모리에 일부 캐시해두며 보완한다. 이를 TLB라 하는데, mmu안에 포함되어 있다.
ptbr(page table base register)
valid-invalid bit,
context switching할 때 page table에 해당 프로세스에 대한 valid bit를 마킹한다.
해당 bit의 마킹 유무로 valid한 접근인지 판단할 수 있다.
TLB로 접근할 경우는 어케하지 TLB에도 valid bit가 있나?
-> valid-invalid bit이용
-> 그런데 invalid하지만 디스크에 접근해야할 상황이 있을텐데 어케함(page fault)?
valid-invalid bit와 dirty bit의 차이?
pure demanding pagingd의 한계 극복 위해 어떤 페이지를 우선해서 로드하나?
page table도 메모리에 저장되는데, page-in, page-out에 따라 이 page table도 메모리에서 쫓겨날 수 있음. 이러면 context switching 비용이 너무 커서 이런일없게 관리해야 할 텐데... 방법은?
cpu에 fetch할 때 인자 로드 시에 page fault가 났냐, operation로드 시에 page fault났냐 등에 따라 trap후 instruction을 어떻게 재시작할지 다르다.
copy on write: child프로세스가 쓰기 작업을 하지 않는다면 parent프로세스의 메모리를 또 메모리에 할당할 필요가 없다. 때문에 쓰기 작업을 할때에 부모 프로세스의 메모리를 copy해 load한다.
FIFO / LRU - counter, stack(최근참조되면 다시 최상위에 push - 일반적인 스택이 아님) , reference bit, second chance
free frame없을 때, 기존의 어떤 page를 out시킬 거냐(victim 선정)
thrashing
working set model활용
frame allocation algorithm
어떤 프로세스에게 프레임 많이 줄까?
-> equal VS proportial // global VS local