※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)


이 글을 시작하기 전에... 얼마나 기쁜지 모른다. 이 개념을 알기 위해 얼마나 많은 삽질을 했고 얼마나 많은 가정을 내리고 얼마나 많은 문서를 또는 책을 읽었는가. 우리 스터디 그룹의 이름을 MAYBE 로 만든 주범이 드디어 잡혔다. (Clock Cycle이라는 또 다른 주범이 있기는 하다...)


아무튼 시작해보자. Virtual Memory(가상 메모리)의 진실을 파해치러.


우선 Virtual Memory를 공부하기 전에 필요한 다른 이야기들을 먼저 하고 가자. 


컴퓨터가 메모리를 접근하는 방법은 어떻게 될까? 보통 이론서들에서 이야기하기를, 컴퓨터가 직접적으로 접근할 수 있는 것은 두 개라고 한다. 레지스터와 메모리이다. 그런데 사실, 메모리 같은 경우 직접 접근이 아니라 그러해 보이는 것 뿐이다. 대부분의 컴퓨터는 Physical Memory를 MMU를 통해 한번 거쳐서 접근한다. 즉, 컴퓨터가 메모리에 접근하겠답시고 만들어낸 주소가 사실은 MMU를 거쳐서 가공되어야만 실제 Physical Memory에 접근이 가능하다는 것이다.


여기서 용어를 정리하고 넘어가자. 젤 처음에 컴퓨터가 접근하기 위해서 생성해낸 하나의 주소가 바로 Logical address이다. Virtual address와 같다고 봐도 무방하다. 그리고 이 Logical address가 MMU를 거쳐서 만들어지는 것이 Physical address이다.



그러면 왜 컴퓨터는 Logical address를 생성하여 한번 거쳐서 Physical address로 가는 것일까? 여기에는 여러가지 이유가 있다. CPU가 직접적으로 Physical Memory에 접근이 가능하다면, 일반 사용자들이 만든 어플리케이션들이 역시 그것이 가능하다는 것인데, 이는 보안에 굉장히 취약하다. 그렇다고 MMU를 통해서 가면 보안이 강화되냐?라고 물어보는 사람도 있을 것이다. 대답은. 그렇다 이다. 사실 MMU에서는 아래와 같은 방법을 통해 Physical Memory에 접근하는 것을 검사해준다.




그렇다. 만일 Logical address가 Kernel space에 접근하려하는 것 같으면 MMU에서 막힌다. 혹은 다른 프로그램이 사용하고 있는 메모리 영역에 접근하려하는 시도가 발생할 때 역시 MMU에서 막히게 된다. 


Logical address를 사용하는 또 다른 이유는 프로그래머의 편의를 도모하기 위해서이다. 이 부분에 대한 자세한 설명은 조금 나중에 하기로 하자. 지금하면 헷깔릴 것 같다. 굉장히 중요한 내용이 될 것이다.


알아야 할 또 다른 내용은 바로 Address Binding이다. 우선, 하나의 프로그램이 컴파일되고 메모리에 로드되는 과정을 이해할 필요가 있다. 아래의 표를 보고 이야기 해보자. 



하나의 소스 프로그램(*.c)이 컴파일러와 어셈블러에 의해 처리되면 object file(*.o 파일)이 만들어진다. 이 파일이 링커에 의해 다른 object file과 연결된다. 여기서 연결되는 대표적인 object file같은 것이 예를 들어 printf.o 같은 것이 있다. C프로그램을 작성하다보면 printf 함수를 많이 사용하게 된다. 이 printf 함수를 사용할 수 있는 이유는 바로 C를 설치할 때 printf 함수가 printf.o라는 object file로 존재하기 때문에 우리가 불러 쓸 수 있는 것이다. 그런 다음에 메모리에 올려진 후 프로그램을 실행할 수 있는 것이다.


전체 과정을 대략적으로 이해했으니 구체적인 예를 들어서 설명해보자.

보통 하나의 C 코드가 컴파일을 거치게 되면  생성되는 파일이 .S 파일이다. 이는 어셈블리 언어로 되어 있고 다음과 같은 형태를 보인다.



젤 왼쪽에 있는 것은 offset이다. 대충 어떤 기준으로부터 몇 바이트 떨어져있는지에 대한 정도라고 생각하면 된다. (그 기준은 나중에 언급될 것이니 궁금해도 참아보자.) 이 object file이 링커에 의해 링킹이 되면 아래와 같은 코드로 변하게 된다.



젤 왼쪽에 뭔지 모를 숫자들이 막 써있다. 저 숫자들의 정체를 파악하느라 나는 굉장한 시간을 보냈다.(내가 이해한게 맞겠지?) 잘 보면 저 숫자들의 차이가 바로 위에 있는 어셈블리 파일에서 보여진 숫자들의 차와 일치한다. 즉 어셈블리 파일이 실행가능하도록 링커가 어느 공간에 끼워맞춘 것이다. 이 과정을 address binding이라고 한다. 즉 저 왼쪽에 있는 값들은 메모리 주소값이다. 그런데 Physical address는 아니다. Logical address이다. 저 부분이 위에서 말했던 MMU에 의해서 실제 Physical address로 매핑되는 것이다. (실제 Physical address를 볼 수 있는 방법이 있다면 댓글 부탁드려요. 찾아보려 했는데 잘 안나오네요;;) 


이제 저 address binding이 언제 되는지에 대해서 이야기 해보자. 위에서 사용했던 그림을 다시 한번 사용해보자.


오른쪽에 보면 Compile Time, Load Time, Execution Time이라고 적혀있다. 그 시간들이 바로 주소들이 결정되는 시간이다. 


1. Compile Time Binding

컴파일 할 때, 즉 object file을 만들어 낼 때 이미 링킹까지 다 끝내버리는 것이다.


2. Load Time Binding

링커에 의해 주소를 결정하는 것이다.


3. Execution Time Binding

중요한 개념이다. 요즘 거의 모든 컴퓨터는 이 방법을 쓰고 있다고 한다. 실행 시간 중에 주소를 결정하여 메모리에 로딩한다는 것이다. 즉, 프로그램이 실행 중에도 메모리의 이곳 저곳을 돌아다닐 수 있다는 개념이 된다. 


Compile Time Binding과 LoadTime Binding은 logical address와 Physical address의 값이 같다고 한다. 반면 Execution Time Binding은 logical address와 Physical address의 결과가 다르다고 한다. 당연하다. 바로 이 과정이 MMU를 거쳐서 Logical address가 Physical address로 전환되는 것이기 때문이다. 즉, 우리가 말했던 MMU를 거쳐서 실제 메모리 주소를 만들어내는 것은 Execution Time Binding을 가정하고 했던 말들이 된다.


우선은 여기까지 알아두자. 다음 포스팅에서는 Virtual Memory를 이해하기 위한 또 다른 기본 지식을 논하겠다. 그것이 오늘 논한 것 보다 더 중요한 기본 지식이 될 것 같다.

'System Programming' 카테고리의 다른 글

[SP] Virtual Memory (Swapping)  (0) 2013.04.24
[SP] Virtual Memory (Basic Knowledge)  (1) 2013.04.23
[SP] Floating Point Number  (0) 2013.04.15
[SP] Data Representation (2's complement)  (0) 2013.04.11
[SP] Data Representation  (0) 2013.04.09
Posted by 빛나유
,