본문 바로가기
운영체제

윈도우즈 운영체제에서 가상 메모리(Virtual Address)

by oobw 2023. 10. 22.

운영체제에서 메모리 관리와 가상 메모리는 핵심적인 개념입니다. 이번에는 가장 많이 사용하는 운영체제 중 하나인 윈도우즈 운영체제에서 가상 메모리가 어떻게 구현되어 있는지를 소개합니다. 특히, 윈도우즈의 가상 주소 메모리와 가상 주소 공간에 대해 자세히 알아보도록 하겠습니다.

1. 배경지식: 가상 메모리

가상 메모리란?

가상 메모리는 컴퓨터 시스템의 메모리 관리 방법 중 하나로, 물리적인 메모리 크기를 초과하는 프로그램 실행을 가능하게 하는 기술입니다. 이 기술은 프로그램이 사용하는 주소 공간을 물리 메모리와 디스크 공간(주로 스왑 영역 또는 페이징 파일)에 나눠 저장함으로써, 물리 메모리보다 큰 메모리 영역을 제공하는 것처럼 보이게 합니다.

왜 가상메모리가 필요한가?

  • 프로세스 독립성: 각 프로세스는 자신만의 독립된 가상 주소 공간을 가지므로, 다른 프로세스의 메모리에 영향을 미치지 않습니다.
  • 보안: 프로세스 간 메모리 영역을 분리하여, 하나의 프로세스가 다른 프로세스의 메모리를 무단으로 접근하는 것을 방지합니다.
  • 메모리 활용 효율: 실제 물리 메모리보다 큰 가상 메모리를 통해 프로그램을 실행할 수 있게 해주며, 이는 스왑 영역과 함께 작동하여 가능해집니다.
  • 일관된 주소 공간: 프로세스는 항상 동일한 가상 주소 공간에서 시작되므로, 메모리 위치의 변동성을 걱정할 필요가 없습니다.

가상 메모리 공간이란?

가상 메모리와 가상 메모리 공간은 종종 혼동될 수 있는데, 이 둘은 다른 개념입니다.

먼저 가상 메모리는 물리적 메모리의 한계를 넘어 프로그램 실행을 지원하는 시스템을 의미합니다.

 

반면에, 가상 메모리 공간은 프로세스가 사용하는 메모리 주소의 범위, 즉 프로세스가 실행될 때 해당 프로세스만의 독립적인 메모리 주소 공간을 의미합니다. 이 주소 공간은 물리적 메모리의 실제 위치와는 독립적이며, 운영체제와 하드웨어의 지원을 받아 가상 주소를 물리 주소로 변환합니다.

2. 윈도우즈의 가상 메모리 구현

페이징: 윈도우는 가상 메모리를 페이지라는 단위로 관리합니다. 일반적으로, 각 페이지의 크기는 4KB로 설정되며, 이 페이지들은 물리 메모리 안의 페이지 프레임에 매핑되어 있습니다.

 

페이지 디렉터리와 페이지 테이블: 윈도우는 가상 주소를 물리 주소로 변환하기 위해 페이지 디렉터리와 페이지 테이블을 활용합니다. 페이지 디렉터리에는 페이지 테이블들에 대한 참조가 있고, 페이지 테이블 내에는 실제 물리 주소에 대한 참조가 포함되어 있습니다.

 

페이징 파일 (Pagefile.sys): 윈도우즈는 가상 메모리 구현을 위해 페이징 파일을 활용합니다. 이 파일은 대체로 C:\ 드라이브에 "pagefile.sys" 이름으로 저장되며, RAM의 사용 가능한 공간이 충분하지 않을 경우, 이 파일이 디스크 상에서 임시 저장 영역으로 사용됩니다. 윈도우즈는 사용자에게 가상 메모리 설정을 조절할 수 있는 옵션을 제공합니다. '시스템 속성' 메뉴에서 '고급 시스템 설정' 옵션을 선택한 후 '성능' 탭 아래의 '설정' 버튼을 클릭하면, '가상 메모리' 설정 창으로 이동할 수 있습니다. 여기서 페이징 파일의 크기 조절이나 다른 드라이브에 페이징 파일을 추가하는 작업을 수행할 수 있습니다.

 

지연 페이지 할당 (Lazy Allocation) 및 페이지 예측 (Paging Prediction): 윈도우는 메모리의 효율적 사용을 위해 실제로 필요한 시점까지 메모리 할당을 지연시키는 방법을 사용합니다. 프로세스가 메모리 요청을 할 때, 운영체제는 해당 주소 공간을 먼저 예약하되, 실제 데이터가 그 위치에 기록될 때까지는 물리 메모리의 할당을 보류합니다. 추가로, 윈도우는 다가올 페이징 작업을 효율적으로 처리하기 위해 어떤 페이지가 다음에 필요할지를 예측하는 기능도 갖추고 있습니다. 이런 기능을 통해 불필요한 페이징 작업을 줄이고 전체적인 성능을 향상시키게 됩니다.

3. 윈도우즈의 가상 메모리 공간

가상 메모리 공간의 크기

위에서 설명한 바와 같이, 프로세스에 할당 가능한 가상 주소 범위를 "프로세스의 가상 메모리 공간"이라고 부릅니다. 윈도우에서는 32비트와 64비트 시스템에 따라 가상 메모리 공간의 크기가 다르게 설정됩니다.

 

32비트 시스템: 약 4GB의 가상 메모리 공간을 사용합니다. 여기서 2GB는 유저 모드 프로세스를 위한 것이고, 나머지 2GB는 시스템(커널) 영역에 할당됩니다.


64비트 시스템: 가상 메모리 공간의 크기가 테라바이트 단위로 확장됩니다. 그러나 실제로 사용되는 영역은 시스템의 구성과 실제 사용 중인 메모리 양에 따라 다릅니다.

유저 프로세스 메모리 공간과 시스템(커널) 프로세스 메모리 공간

윈도우에서 가상 메모리 공간은 유저 프로세스와 시스템(커널) 프로세스가 반반씩 나눠서 사용합니다. 하위 공간은 유저 프로세스가 사용하며, 상위 공간은 커널 프로세스가 사용합니다.

각 유저 모드 프로세스는 독립된 가상 주소 공간을 가지지만, 커널 모드에서 실행되는 코드는 "시스템 공간"이라 불리는 단일 가상 메모리 공간을 공유합니다. 유저 모드 프로세스의 가상 주소 공간은 "사용자 공간"으로도 불립니다. 아래 그림에 하위 유저 프로세스 메모리 공간에는 여러 개의 프로세스가 동시에 맵핑이 되어있지만 상위 메모리 공간에는 커널이 사용하는 시스템 주소 공간이 한 개 매핑되어있는 것을 볼 수 있습니다.

windows memory layout

32비트 윈도우

사용 가능한 총 가상 주소 공간은 2^32바이트(4GB)입니다. 위에 설명한 대로, 하위 2GB는 사용자 공간으로 사용되며, 상위 2GB는 시스템 공간으로 사용됩니다. 유저 프로세스의 가상 주소 범위는 0x00000000부터 0x7FFFFFFF (2GB), 커널 프로세스는 0x80000000부터 0xFFFFFFFF (2GB)로 설정됩니다.

 

 32비트 운영체제의 경우, 사용자 공간에 2GB 이상을 할당할 수 있는 옵션을 제공합니다. 이를 활용하면 사용자 공간을 최대 3GB까지 확장할 수 있으나, 그에 따라 시스템 공간은 1GB로 줄어듭니다. 사용자 공간을 확장하려면 BCDEdit /set raiseuserva 명령을 사용합니다.

64비트 윈도우

이론적으로 가능한 가상 주소 공간의 크기는 2^64바이트(16엑사바이트)입니다. 그러나 실제로는 이 범위 중 일부만이 사용됩니다. 64비트 윈도우즈에서는 유저 프로세스가 0x00000000000부터 0x7FFFFFFFFFFF (128테라바이트)의 범위를, 시스템 프로세스가 0x80000000000부터 나머지 128테라바이트를 사용합니다.

유저 프로세스 공간

윈도우 운영체제가 부팅되면 커널 프로세스는 항상 동작 상태를 유지하며 가상 메모리 공간의 절반을 점유합니다. 이와 달리, 유저 프로세스는 이전에 설명한 것처럼 단 하나만 존재하는 것이 아닙니다. 여러 유저 프로세스들이 동시에 실행되며, 각각은 0x0000000부터 시작하는 고유한 개인 가상 주소 공간을 갖게 됩니다.

virtual address space for applications

 

예시로, 위에서 언급한 그림은 Notepad.exe와 MyApp.exe라는 두 개의 64비트 프로세스의 가상 주소 공간을 표현하고 있습니다. 이 두 프로세스 모두, 0x0000000000부터 0x7FFFFFFFFFFF까지의 독립적인 가상 주소 공간을 가집니다. 그림에서 음영 처리된 부분은 가상 메모리나 실제 메모리의 한 페이지를 나타내며, 이는 4KB의 크기를 갖습니다.

 

메모장 프로세스는 0x7F793950000에서 시작하여 연속적인 세 개의 가상 주소 페이지를 사용하고 있습니다. 그러나 이 연속된 가상 주소 페이지들은 실제 메모리 내에서는 불연속적으로 위치하게 됩니다. 더불어, Notepad.exe와 MyApp.exe 두 프로세스는 모두 0x7F793950000부터 시작하는 가상 메모리 페이지를 사용하고 있지만, 이 두 프로세스의 해당 가상 페이지들은 실제 메모리 내의 서로 다른 위치에 매핑됩니다.

시스템 메모리 보호

사용자 모드에서 실행되는 코드는 사용자 공간에만 액세스 가능하며 시스템 공간에는 접근할 수 없습니다. 이 제한은 사용자 모드 코드가 보호된 운영 체제의 데이터 구조를 변경하거나 읽는 것을 방지합니다. 반면, 커널 모드에서 실행되는 코드는 사용자 공간과 시스템 공간 모두에 접근이 가능하므로, 현재의 사용자 모드 프로세스의 시스템 공간과 가상 주소 공간 모두에 액세스 할 수 있습니다.

 

커널 모드에서 동작하는 드라이버는 사용자 공간의 주소를 직접 읽거나 쓸 때 매우 주의해야 합니다. 예를 들면, 사용자 공간의 주소에 직접 쓰게 구현되었다면, 직접 쓰기 연산을 수행하기 직전에 커널 코드 실행 중 인터럽트 발생으로 인해 임의의 프로세스로 컨텍스트 스위치가 발생할 수 있습니다. 이 경우 인터럽트를 처리하고 다시 커널 코드가 실행될 때, 원래의 유저 프로세스가 아니라 다른 임의의 프로세스의 컨텍스트일 수 있습니다. 이 상황에서 드라이버의 쓰기 연산이 수행되면, 의도했던 유저 프로세스가 아닌 임의의 프로세스의 메모리에 쓰기 연산이 수행될 가능성이 있습니다.

페이징 풀(Paged pool)과 비페이징 풀(Nonpaged pool)

사용자 공간의 모든 물리적 메모리 페이지는 필요시 디스크 파일로 페이지 아웃될 수 있습니다. 반면, 시스템 공간의 일부 물리적 페이지는 페이지 아웃이 가능하며, 다른 일부는 페이지 아웃이 불가능합니다. 시스템 공간에는 메모리를 동적으로 할당받기 위한 두 영역, 페이징 풀과 비페이징 풀이 존재합니다. 페이징 풀의 메모리는 필요에 따라 디스크 파일로 페이지 아웃될 수 있지만, 비페이징 풀의 메모리는 페이지 아웃이 불가능합니다.

 

마치며

이상으로 사용자와 시스템 간의 프로세스에서 가상 메모리 주소 공간의 구분, 32비트와 64비트 시스템 간의 차이, 그리고 사용자 모드와 커널 모드에서의 메모리 접근 권한 등의 주제를 통해 윈도우 운영체제의 메모리 관리에 대해 알아보았습니다.