문제

Windows 응용 프로그램은 일반적으로 32비트 시스템에서 2GB의 개인 주소 공간을 갖는다는 것은 알려진 사실입니다./3Gb 스위치를 사용하면 이 공간을 3Gb로 확장할 수 있습니다.

운영 체제는 나머지 4Gb를 자체적으로 예약합니다.

내 질문은 왜?

커널 모드에서 실행되는 코드(예:장치 드라이버 코드)에는 자체 주소 공간이 있습니다.운영 체제가 독점적인 4Gb 주소 공간 외에도 여전히 각 사용자 모드 프로세스의 2Gb를 예약하려는 이유는 무엇입니까?

그 이유는 사용자 모드와 커널 모드 호출 간의 전환 때문이라고 생각했습니다.예를 들어, NtWriteFile 커널 디스패치 루틴에 대한 주소가 필요합니다(따라서 시스템이 각 애플리케이션에서 2Gb를 예약하는 이유).하지만, SYSENTER, 커널 모드 코드가 어떤 함수/서비스가 호출되고 있는지 알 수 있을 만큼 시스템 서비스 번호가 충분하지 않습니까?

운영 체제가 각 사용자 모드 프로세스에서 2Gb(또는 1Gb)를 차지하는 것이 왜 그렇게 중요한지 명확하게 설명해 주실 수 있나요?

도움이 되었습니까?

해결책

두 가지 다른 사용자 프로세스에는 다른 가상 주소 공간이 있습니다. 가상의 물리 주소 매핑이 다르기 때문에 TLB 한 사용자 프로세스에서 다른 사용자 프로세스로 컨텍스트를 전환 할 때 캐시가 무효화됩니다. TLB에 이미 캐시 된 주소가 없으면 메모리 액세스가 발생하면 결함과 도보로 인해 이것은 매우 비쌉니다. PTE에스.

SYSCALL에는 사용자 → 커널 및 커널 → 사용자의 두 가지 컨텍스트 스위치가 포함됩니다. 이 속도를 높이려면 커널 사용을 위해 1GB 또는 2GB의 가상 주소 공간을 예약하는 것이 일반적입니다. 가상 주소 공간은 이러한 컨텍스트 스위치에서 변경되지 않기 때문에 TLB 플러시가 필요하지 않습니다. 이는 각 PTE의 사용자/감독자 비트에 의해 활성화되어 커널 공간에있는 동안 커널 메모리에만 액세스 할 수 있도록합니다. 페이지 테이블이 동일하더라도 사용자 공간은 액세스 할 수 없습니다.

커널 사용을위한 독점적으로 하나의 개별 TLB에 대한 하드웨어 지원이 있었다면이 최적화는 더 이상 유용하지 않습니다. 그러나 헌신 할 공간이 충분하다면 더 큰 TLB를 만드는 것이 더 가치가있을 것입니다.

X86의 Linux는 "4G/4G 분할"이라는 모드를 지원했습니다. 이 모드에서 사용자 공간에는 전체 4GB 가상 주소 공간에 대한 전체 액세스 권한이 있으며 커널에는 전체 4GB 가상 주소 공간이 있습니다. 위에서 언급 한 바와 같이 비용은 그입니다 모든 SYSCALL은 사용자와 커널 메모리간에 데이터를 복사하기 위해보다 복잡한 루틴과 함께 TLB 플러시가 필요합니다. 이는 최대 30%의 성능 페널티를 부과하기 위해 측정되었습니다.


이 질문이 원래 질문하고 답변 된 이후로 시간이 바뀌 었습니다. 64 비트 운영 체제가 훨씬 더 널리 퍼져 있습니다. x86-64의 현재 OS에서 가상 주소는 0에서 2까지47-1 (0-128TB)는 사용자 프로그램에 허용되는 반면 커널은 2의 가상 주소 내에 영구적으로 상주합니다.47×(217-1) ~ 264-1 (또는 -2에서47 주소를 서명 된 정수로 취급하는 경우).

64 비트 창에서 32 비트 실행 파일을 실행하면 어떻게됩니까? 당신은 모든 가상 주소가 0에서 2까지32 (0-4GB)는 쉽게 사용할 수 있지만 기존 프로그램에서 버그 노출을 피하기 위해 32 비트 실행 파이브는 다시 컴파일되지 않는 한 여전히 0-2GB로 제한됩니다. /LARGEADDRESSAWARE. 사람들에게는 0-4GB에 액세스 할 수 있습니다. (이것은 새로운 깃발이 아닙니다. 32 비트 Windows 커널에 동일하게 적용됩니다. /3GB 기본 2G/2G 사용자/커널 분할을 3G/1G로 변경했지만 물론 3-4GB는 여전히 범위를 벗어났습니다.)

어떤 종류의 버그가있을 수 있습니까? 예를 들어, QuickSort를 구현하고 두 개의 포인터가 있다고 가정합니다. a 그리고 b 배열의 시작과 지나간을 지적합니다. 중간을 피벗으로 선택하는 경우 (a+b)/2, 두 주소가 2GB 미만인 한 작동하지만 둘 다 위에 있으면 추가로 정수 오버플로가 발생하고 결과는 배열 외부에 있습니다. (올바른 표현은 a+(b-a)/2.)

제쳐두고, 기본 3G/1G 사용자/커널 분할이 포함 된 32 비트 리눅스는 역사적으로 스택이 2-3GB 범위에있는 프로그램을 실행 했으므로 이러한 프로그래밍 오류는 빠르게 플러시 될 수 있습니다. 64 비트 Linux는 32 비트 프로그램에 0-4GB에 액세스 할 수 있습니다.

다른 팁

레이몬드 첸이 있었다 이 주제에 관한 기사.

Windows(다른 OS와 마찬가지로)는 커널 + 드라이버보다 훨씬 더 많은 기능을 제공합니다.

귀하의 응용 프로그램은 커널 공간에만 존재하지 않는 많은 OS 서비스에 의존합니다.프로세스의 자체 주소 공간에 매핑될 수 있는 버퍼, 핸들 및 모든 종류의 리소스가 많이 있습니다.창 핸들이나 브러시 등을 반환하는 Win32 API 함수를 호출할 때마다 이러한 항목은 프로세스 어딘가에 할당되어야 합니다.따라서 Windows의 일부는 커널에서 실행되고, 다른 부분은 자체 사용자 모드 프로세스에서 실행되며, 응용 프로그램이 직접 액세스해야 하는 일부는 주소 공간에 매핑됩니다.이 중 일부는 피하기 어렵지만 중요한 추가 요소는 성능입니다.만약에 모든 Win32 호출에는 컨텍스트 전환이 필요하므로 성능에 큰 타격을 줄 수 있습니다.그 중 일부가 의존하는 데이터가 이미 주소 공간에 매핑되어 있기 때문에 사용자 모드에서 처리할 수 있는 경우 컨텍스트 전환이 방지되고 꽤 많은 CPU 주기가 절약됩니다.

따라서 모든 OS 요구 사항 일부 따로 설정된 주소 공간의 양.저는 Linux가 기본적으로 OS에 대해 1GB만 설정한다고 생각합니다.

MS가 윈도우에서 2GB로 안착한 이유는 레이먼드 첸의 블로그에서 한 번 설명한 바 있다.링크가 없고 자세한 내용은 기억나지 않지만 Windows NT는 원래 Alpha 프로세서를 대상으로 했기 때문에 결정이 내려졌고 Alpha에서는 50/50을 수행할 정말 좋은 이유가 있었습니다. 나뉘다.;)

이는 Alpha의 32비트 및 64비트 코드 지원과 관련이 있었습니다.:)

커널 모드에서 실행되는 코드 (예 : 장치 드라이버 코드)에는 자체 주소 공간이 있습니다.

아니 그렇지 않아. X86 프로세서에서 프로세스의 사용자 모드 부분과 해당 주소 공간을 공유해야합니다. 그렇기 때문에 커널이 공간을 충분히 예약하고 주소 공간을 유한해야합니다.

최선의 대답은 OS 디자이너들이 당신이 돌봐야 할 때까지 사람들이 64 비트 창을 사용할 것이라고 생각했다고 생각합니다.

그러나 여기에 a 더 나은 토론.

답의 일부는 마이크로 프로세서 아키텍처의 역사와 관련이 있습니다. 다음은 내가 아는 것 중 일부가 있습니다. 다른 것들은 더 최근의 세부 사항을 제공 할 수 있습니다.

Intel 8086 프로세서에는 메모리에 대한 세그먼트 오프셋 아키텍처가 있었으며 20 비트 메모리 주소를 제공하므로 1MB의 총 주소 지정 가능한 물리적 메모리가 있습니다.

시대의 경쟁 프로세서와 달리 - Zilog Z80과 같은 Intel 8086은 하나만 가지고있었습니다. 주소 공간 전자 메모리뿐만 아니라 키보드, 직렬 포트, 프린터 포트 및 비디오 디스플레이와 같은 작은 주변 장치와의 모든 입력/출력 통신을 수용해야했습니다. (비교를 위해 Zilog Z80에는 액세스를위한 전용 어셈블리 opcode가있는 별도의 입력/출력 주소 공간이있었습니다)

끊임없이 점점 더 많은 주변 확장을위한 공간을 허용 할 필요가 있었기 때문에 주소 공간을 0-640K에서 전자 메모리로 분류하기로 한 원래 결정과 640K에서 "입력/출력, ROM, 비디오 메모리 등) 1MB.

X86 라인이 성장하고 진화하고 PC가 그들과 함께 진화함에 따라, 4G 주소 공간의 2g/2g 분할로 끝나는 유사한 체계가 사용되었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top