티스토리 뷰

Study/OS

[Memory] Indirection

생각많은 소심남 2014. 9. 1. 12:37

* 이 글은 coursera에서 제공되는 HW/SW Interface 강의를 요약한 내용입니다.


Virtual Memory라는 말을 들어본 사람이라면 왜 이름에 Virtual 이 들어갔는지 궁금할 것이다. 말그대로 가상이라는 말인데, 우리가 하드웨어로 장착하는 DRAM말고도 또다른 영역이 존재하나 싶기도 하다. 그런데 그 필요성을 따지다보면 Virtual Memory가 왜 필요한지를 알 수 있지 않을까 싶다. 

 memory는 byte로 구성된 아주 큰 array다. 그리고 각 array에 속해있는 element는 자기가 가지고 있는 address를 이용해서 읽거나 쓸 수 있었다. 이런게 옛날에는 당연하게 여겨지는 원칙이었지만 문제는 64bit addressing을 쓰게 되면서부터다. array의 element에 접근하기 위해서는 앞에서 언급한 것처럼 address를 이용해야 하는데 64bit addressing을 하게 되면 최대로 표현할 수 있어야 하는 address는 2^64 = 16 exa byte 가 되게 된다. 16 exabyte면 1 테라바이트 하드를 16백만개를 쌓아야 할 데이터량인데 고작 우리가 PC에 장착할 수 있는 Physical DRAM은 데스크탑 기준으로 봤을때는 최대 64GB다. 그럼 이걸 어떻게 표현할 수 있을까?


또 다른 문제는 지난 포스트에서 다뤘던 Process와 상관있다. 그때 언급했는지는 잘 모르겠지만 Process 각각은 자기만의 Memory영역을 가진다. stack, heap, data영역 등을 가지는데 만약 이런 게 Physical DRAM에서는 어떻게 저장이 될까?그냥 무작정 저장하기에는 너무 비효율적이지 않을까 싶다. 간혹 어떤 process는 idle state임에도 memory에 할당되어 계속 system resource를 소비할 것이고, 어떤 건 active 상태임에도 allocate되지 않아서 또다른 문제를 야기할 것이다.


 또 어떤 process들끼리는 같은 memory 영역을 공유하는 케이스도 있을 것이다. 예를 들어서 shared library를 쓰는 경우는 같은 process가 각각 library를 생성하는 것보다는 어떤 영역에 shared library를 올려놓고 쓰면 조금 효율적으로 쓸 수 있을 것이다. 문제는 이렇게 공유하는 케이스 중에서 한 process가 memory에 있는 data를 수정하게 되는 경우다. 분명 직접적으로 memory에 수정하게 된다면 또다른 process는 그 수정된 내용을 모르고 있다가 나중에 읽을때 문제가 발생할 것이다. (보통 이럴때 COW같은 방법을 쓰기도 한다.)


이런 연유에서 Virtual Memory라는 개념을 쓰고, 위와 같은 문제를 해결하는 mechanism이 indirection이라는 것이다.


큰 맥락은 Memory와 Memory를 접근하려는 개체 사이에 어떤 layer를 삽입하자는 것이다. 가령 이름을 이용해서 어떤 것을 찾으려고 할 때는 Memory로 직접적으로 접근할 때는 name과 맞는 address를 일일이 memory 부분에서 찾아야 했겠지만 indirection을 쓰게 되면 layer에서 name만 찾아봄으로써 찾고자 하는 것을 얻을 수 있다. 이게 이름이 될 수도 있는 것이고, pointer가 될 수 있는 것이고, container가 될 수도 있는 것이다. 개념은 name에 대한 reference가 존재한다는 것이다. 이런 예는 우리 주변에서도 찾아볼 수 있다. 제일 대표적인 게 Domain Name Service(DNS)일텐데, google.com에 접근하고자 할때에도 우리가 IP를 넣지 않고, www.google.com으로 접속할 수 있는 이유가 어딘가에 LookUp Table이 존재하기 때문이다. 이런 식으로 유연하게 대체할 수 있다는 장점이 있다. 그러면 Virtual Memory에서는 어떤식으로 indirection이 발생할까?


쉽게 말하면 process 각각은 자기만의 virtual memory를 가지고 있고, process가 Physical memory에 접근하고자 할 때는 

Virtual memory -> (뭔가 mapping되어 있는 list) -> Physical memory

의 경로를 거쳐서 접근하게 된다. 이렇게 하면 이전에 문제로 언급되었던 용량 문제는 해결할 수 있게 된다. 즉, process마다 모두 physical memory에 load할 필요없이 어딘가에 저장하면서 필요한 것만 이 mapping table을 거치면 되는 것이다. 이때 process내에서 쓰이는 단위가 Virtual address space라는 것이다.

 자 그러면 용량적인 문제를 해결했다고는 하지만 없는 것을 있다고 할 수 없는 노릇이다. 분명 process에 있는 데이터도 어딘가에는 실재해야 physical memory로도 올릴 수도 있을텐데 그러면 이런 것들은 과연 어디에 존재할까? 딱 컴퓨터 시스템을 놓고 봤을 때 뭔가 대용량으로 저장할 수 있는 하드웨어가 뭐가 있는지 따져보면 답이 디스크밖에 없다는 것을 알 수 있다. 즉, virtual memory는 디스크에 있다. 아마 예전에 하드디스크 사이즈가 부족하다고 생각한 사람은 아마 이런 방법을 해봤을 것이다.


윈도우에서는 이런 virtual memory를 디스크에서 관리할 수 있게 따로 메뉴화가 되어 있고, 네모안에 들어 있는 값에 따라서 하드디스크내에서 virtual memory가 차지하는 영역이 달라진다. 물론 요즘과 같이 램 크기가 크고, 하드디스크 용량도 큰 상태에서는 이런 문제는 거의 고려하지 않게 되었다. 아무튼 이런식으로 virtual memory를 관리하게 된다. 결국 이런 내용을 통하면 process는 virtual address space를 통해서 physical memory에 들어있는 내용에도 접근할 수도 있어야 하고, 혹은 disk에 있는 virtual memory에도 접근할 수 있어야 한다. 그래서 mapping 과정은 다음과 같이 묘사할 수 있다.


이런 건 cpu가 memory에 있는 내용을 읽을 때도 마찬가지다. CPU가 memory의 특정 영역을 접근하기 위해서 일일이 address를 찾는 것보다는 중간에 위처럼 뭔가 변환하는 과정을 통해서 indirection을 이뤄지게 하면 조금 더 유연하게 memory access를 할 수 있다. 그런데 잠깐 고민해볼게 만약 앞에서 언급한 문제가 발생하지 않는 시스템, 즉 MCU를 이용한 임베디드 시스템의 경우는 어떤 식으로 memory access를 할 지에 대한 것이다. 아마 아두이노나 AVR을 써본 사람이라면 실제로 하드웨어에서 쓸 수 있는 메모리 용량이 일반적인 PC에 비해서 엄청 작다는 것을 알 수 있다. 그냥 이럴때는 physical address를 통해서 바로 main memory에 접근하면 된다.

이때는 무언가를 변환해서 찾는 과정이 overhead로 작용하기 때문에 실제 주소만 가지고 찾는 것으로도 충분히 처리할 수 있다. 우리가 쓰고 있는 것처럼 고용량 memory를 쓰는 경우는 다음과 같이 접근하게 된다.

앞에서 언급한 것처럼 CPU가 memory access를 하기 위해서는 그 큰 memory에 대한 address를 일일이 가질 필요없이 중간에 Memory Management Unit(MMU) 을 거치게 하면 앞에서 설명했던 indirection을 구현할 수 있다. 이에 대한 내용은 다음 포스트에서 조금 더 다뤄보려고 한다.

'Study > OS' 카테고리의 다른 글

[Memory] Sample Memory System  (7) 2014.09.03
[Memory] Address Translation  (1) 2014.09.02
[Memory] Virtual memory caches  (5) 2014.09.01
[Process] Fork-exec Model  (0) 2014.08.29
[Process] Creating New Processes  (0) 2014.08.29
[Process] What is a process?  (2) 2014.08.29
[Process] Exceptional Control  (0) 2014.08.28
댓글