Windows Internals 다시보기 03
* 아직은 많이 부족하기 때문에 제가 자신이 생길 때 까지 본 글은 제 블로그에 대한 링크만 허용합니다.
프로세스는 자신만의 메모리 공간을 가지고 있습니다.
모든 x86 시스템 (일명 32비트 OS)는 총 4G 까지 메모리를 사용할 수 있습니다.
이 4G의 메모리를 0000,0000 부터 FFFF,FFFF 까지의 주소를 갖게 됩니다.
Windows의 메모리는 유저 메모리 공간과 커널 메모리 공간이 분리 되어 있습니다.
하지만 유저 프로세스는 실제로 0000,0000 ~ 7FFF,FFFF 까지 즉 2G의 메모리 공간만 사용하고 8000,0000 ~ FFFF,FFFF 는 커널 공간에서 사용하게 됩니다.
기본적으로 CPU에는 Privileged level 을 통해 실행 명령어를 제한 합니다. 이를 Ring 이라 부르며 인텔 CPU는 Ring 0 ~ 3 에서 0과 3만을 사용합니다.
그리고 높은 권한이 필요한 명령어인 인터럽트를 시작 및 중지한다든지 하는 일들은 Ring 0에서만 돌아가게 해서 권한을 조정했죠.
그리고 Windows는 여기에 아예 접근할 수 있는 메모리 자체를 분리해 버렸습니다. 보통은 유닉스 계열을 모놀릭 커널이라 부르고 Windows는 마이크로 커널이라 부르는데, 이는 바로 유저 프로세스 메모리 공간과 커널 메모리 공간을 정적으로 분리했기 때문입니다. (빠른 처리를 위해 Win32k.sys 서브시스템 및 TCP/IP등이 커널 모드에 있으니 정확한 의미의 마이크로 커널 운영체제는 아닙니다.)
각 유저 프로세스는 임의로 0000,0000 ~ 7FFF,FFFF 까지 접근하고 동일 Windows OS 즉 커널로부터 서비스를 받지만 커널 메모리 공간인 8000,0000 ~ FFFF,FFFF 까지 접근이 차단되어 있습니다.
Windows는 이를 통해 커널의 안정성을 보장할 수 있습니다. 위와 같은 구조라면 Notepad.exe에 문제가 발생하더라도 해당 프로세스는 실행에 문제가 발생하겠지만 이는 커널까지 영향을 줄 수 없고, Iexplorer.exe 및 windbg.exe 까지 영향을 받진 않습니다.
메모리 사용의 효율성을 위해 VAD를 이용하여 메모리 주소를 사용합니다.
프로세스는 2G의 메모리를 사용한다고 생각하지만 실제로는 위의 그림과 같이 실제 사용하는 부분만 VAD로 정의 되어 실제 메모리나 Disk에 페이징 파일로 저장되게 됩니다.
다시 말해 메모리 사용를 효율적으로 사용하기 위해 VAD를 이용하여 쓸 공간을 지정해 놓고 쓰게 됩니다.
위의 예에서 확인 할 수 있는 것과 같이 실제로 이 notepad.exe 프로세스는 2G의 메모리를 사용하는 것이 아니라 최대 가상 메모리 48Mb 까지를 이용하고 있습니다.
PeakVirtualSize 48 Mb
이 VAD는 Tree 구조로 되어 있는데 이 VAD의 총 합이 이 프로세스가 사용하는 총 메모리의 합이 됩니다.
아래 그림과 같이 VAD는 자신이 할당 받은 가상 메모리의 범위와 자식 노트에 대한 링크로 이루어져 있습니다.
위의 notepad.exe의 예를 보자면 (VadRoot 81afd5f0 Vads 101 …
VAD 81afd5f0가 이 트리의 꼭대기가 됩니다. 그리고 총 101개의 VAD를 가지고 있는 것을 알 수 있습니다.
우리는 각 VAD에 대한 정보를 좀 더 상세하게 확인 할 수 있습니다.
아래는 특정VAD의 Root 주소를 통하여 실제 VAD에 대한 내용을 확인한 결과 입니다. 각 VAD의 ID와 레벨 그리고 시작 번지 및 종료 번지등의 정보를 확인 할 수 있습니다. (출력 값에서 시작 및 종료 주소값은 4K를 곱해야 원래 주소값이 됩니다. 즉 아래의 0x10 번지에서 시작하는 경우 가상 주소는 0x10000 이 됩니다.
kd> !vad 859aad30
VAD level start end commit
85a77c40 ( 5) 10 10 1 Private READWRITE
855e6148 ( 4) 20 20 1 Private READWRITE
85a5e520 ( 5) 30 6f 4 Private READWRITE
855850b8 ( 3) 70 74 0 Mapped READONLY
855e46c0 ( 5) 80 17f 8 Private READWRITE
855b80b0 ( 4) 180 18f 0 Mapped READWRITE
85624410 ( 5) 190 1a5 0 Mapped READONLY
855b7f10 ( 2) 1b0 1f0 0 Mapped READONLY
85621960 ( 5) 200 240 0 Mapped READONLY
855869a0 ( 4) 250 255 0 Mapped READONLY
855b8f40 ( 5) 260 2a0 0 Mapped READONLY
85614778 ( 3) 2b0 377 0 Mapped EXECUTE_READ