[windows] Linux보다 Windows에서 새 프로세스를 만드는 데 더 많은 비용이 드는 이유는 무엇입니까?

Windows 상자에서 새 프로세스를 만드는 것이 Linux보다 더 비싸다고 들었습니다. 이것이 사실입니까? 누군가 더 비싼 이유에 대한 기술적 이유를 설명하고 그 이유 뒤에있는 설계 결정에 대한 역사적 이유를 제공 할 수 있습니까?



답변

mweerden : NT는 첫날부터 다중 사용자를 위해 설계되었으므로 이것이 실제로 이유가 아닙니다. 그러나 유닉스와는 대조적으로, 멀티 프로세싱보다 멀티 스레딩을 선호하기 때문에 NT에서 프로세스 생성이 유닉스보다 NT에서 덜 중요한 역할을한다는 점이 맞습니다.

Rob, COW를 사용할 때 포크가 상대적으로 저렴하다는 것은 사실이지만 실제로는 포크 뒤에는 대부분 exec가 따릅니다. 그리고 임원은 모든 이미지도로드해야합니다. 따라서 포크의 성능을 논의하는 것은 진실의 일부일뿐입니다.

프로세스 생성 속도를 논의 할 때 NT와 Windows / Win32를 구분하는 것이 좋습니다. NT (즉 커널 자체)가 진행되는 한, 프로세스 생성 (NtCreateProcess)과 스레드 생성 (NtCreateThread)이 평균적인 유닉스 에서처럼 상당히 느리다고 생각하지 않습니다. 조금 더 진행될 수 있지만 여기서 성능 차이에 대한 주된 이유는 보이지 않습니다.

그러나 Win32를 살펴보면 프로세스 생성에 상당한 오버 헤드가 추가된다는 것을 알 수 있습니다. 첫째, CSRSS가 LPC를 포함하는 프로세스 생성에 대한 알림을 받아야합니다. 최소한 kernel32를 추가로로드해야하며 프로세스가 완전한 Win32 프로세스로 간주되기 전에 수행 할 여러 추가 부기 작업 항목을 수행해야합니다. 그리고 매니페스트 구문 분석, 이미지에 호환성 심이 필요한지 확인, 소프트웨어 제한 정책 적용 여부 확인, yada yada로 인해 부과되는 모든 추가 오버 헤드를 잊지 마십시오.

즉, 프로세스, VA 공간 및 초기 스레드의 원시 생성 외에도 수행해야하는 모든 사소한 작업의 합계에서 전반적인 속도 저하를 봅니다. 그러나 처음에 말했듯이-멀티 태스킹보다 멀티 스레딩을 선호하기 때문에이 추가 비용으로 심각한 영향을받는 유일한 소프트웨어는 제대로 이식되지 않은 Unix 소프트웨어입니다. Chrome 및 IE8과 같은 소프트웨어가 갑자기 다중 처리의 이점을 재발견하고 프로세스를 자주 시작하고 해체하기 시작하면 이러한 상황이 변경되지만 …


답변

유닉스에는 현재 프로세스를 두 개로 ‘분할’하는 ‘포크’시스템 호출이 있으며 첫 번째 프로세스와 동일한 두 번째 프로세스를 제공합니다 (포크 호출의 반환 모듈로). 새 프로세스의 주소 공간이 이미 실행 중이므로 Windows에서 ‘CreateProcess’를 호출하고 exe 이미지, 관련 dll 등을로드하는 것보다 저렴해야합니다.

포크의 경우 OS는 두 새 프로세스와 관련된 메모리 페이지에 대해 ‘기록 중 복사’의미 체계를 사용하여 각 프로세스가 이후에 수정하는 페이지의 자체 복사본을 얻도록 할 수 있습니다.


답변

JP가 말한 내용에 추가 : 대부분의 오버 헤드는 프로세스의 Win32 시작에 속합니다.

Windows NT 커널은 실제로 COW 포크를 지원합니다. SFU (Microsoft의 Windows 용 UNIX 환경)는이를 사용합니다. 그러나 Win32는 포크를 지원하지 않습니다. SFU 프로세스는 Win32 프로세스가 아닙니다. SFU는 Win32와 직교합니다. 두 환경 모두 동일한 커널에 구축 된 환경 하위 시스템입니다.

에 대한 out-of-process LPC 호출 외에도 CSRSSXP 이상에서는 응용 프로그램 호환성 데이터베이스에서 프로그램을 찾기 위해 응용 프로그램 호환성 엔진 에 대한 out-of-process 호출이 있습니다. 이 단계는 성능상의 이유로 WS2003에서 호환성 엔진비활성화 하는 그룹 정책 옵션을 Microsoft가 제공하는 충분한 오버 헤드를 발생시킵니다 .

Win32 런타임 라이브러리 (kernel32.dll 등)는 UNIX, SFU 또는 기본 프로세스에 적용되지 않는 시작시 많은 레지스트리 읽기 및 초기화를 수행합니다.

기본 프로세스 (환경 하위 시스템 없음)는 생성 속도가 매우 빠릅니다. SFU는 프로세스 생성을 위해 Win32보다 훨씬 적게 수행하므로 프로세스도 빠르게 생성됩니다.

2019 년 업데이트 : LXSS 추가 : Linux 용 Windows 하위 시스템

Windows 10 용 SFU를 대체하는 것은 LXSS 환경 하위 시스템입니다. 100 % 커널 모드이며 Win32가 계속 보유하고있는 IPC가 필요하지 않습니다. 이러한 프로세스에 대한 Syscall은 lxss.sys / lxcore.sys로 직접 전달되므로 fork () 또는 기타 프로세스 생성 호출은 생성자에게 총 1 개의 시스템 호출 만 발생합니다. [인스턴스라고하는 데이터 영역]은 모든 LX 프로세스, 스레드 및 런타임 상태를 추적합니다.

LXSS 프로세스는 Win32 프로세스가 아닌 기본 프로세스를 기반으로합니다. 호환성 엔진과 같은 모든 Win32 관련 항목은 전혀 관여하지 않습니다.


답변

Rob Walker의 답변 외에도 : 요즘에는 네이티브 POSIX 스레드 라이브러리와 같은 것이 있습니다. 그러나 오랫동안 유닉스 세계에서 작업을 “위임”하는 유일한 방법은 fork ()를 사용하는 것이 었습니다 (그리고 여전히 많은 상황에서 선호됩니다). 예 : 일종의 소켓 서버

socket_accept ()
포크()
if (아이)
    handleRequest ()
그밖에
    goOnBeingParent ()

따라서 포크의 구현은 빨라야하고 시간이 지남에 따라 많은 최적화가 구현되었습니다. Microsoft는 새로운 프로세스를 만들고 프로세스 간 통신을 사용하는 대신 CreateThread 또는 광섬유를 승인했습니다. CreateProcess를 fork와 비교하는 것은 “공정”하지 않다고 생각합니다. fork / exec를 CreateProcess와 비교하는 것이 더 적절할 것입니다.


답변

이 문제의 핵심은 두 시스템의 역사적 사용입니다. (그 전에 DOS) 윈도우는 원래 위해 단일 사용자 시스템이었다 개인용 컴퓨터. 따라서 이러한 시스템은 일반적으로 항상 많은 프로세스를 생성 할 필요가 없습니다. (매우) 간단히 말해서, 프로세스는 외로운 사용자가 요청할 때만 생성됩니다 (우리 인간은 상대적으로 말해서 매우 빠르게 작동하지 않습니다).

Unix 기반 시스템은 원래 다중 사용자 시스템과 서버였습니다. 특히 후자의 경우 특정 작업을 처리하기 위해 프로세스를 분리하는 프로세스 (예 : 메일 또는 http 데몬)가있는 경우가 드물지 않습니다 (예 : 하나의 수신 연결 처리). 이를 수행하는 데 중요한 요소는 저렴한 fork방법 (Rob Walker ( 47865 )이 언급했듯이 처음에는 새로 생성 된 프로세스에 동일한 메모리를 사용함 )이며, 이는 새 프로세스가 필요한 모든 정보를 즉시 확보하므로 매우 유용합니다.

적어도 역사적으로 유닉스 기반 시스템이 빠른 프로세스 생성을 필요로하는 것은 Windows 시스템보다 훨씬 더 크다는 것은 분명합니다. 유닉스 기반 시스템은 여전히 ​​매우 프로세스 지향적 인 반면 Windows는 역사상 스레드 지향적이었을 것입니다 (스레드는 반응 형 애플리케이션을 만드는 데 유용함).

면책 조항 : 나는 결코이 문제에 대한 전문가가 아니므로 내가 틀렸다면 용서하십시오.


답변

어, “이쪽이 더 낫다”는 정당화가 많이 진행되고있는 것 같습니다.

나는 사람들이 “Showstopper”를 읽음으로써 이익을 얻을 수 있다고 생각한다. Windows NT 개발에 관한 책.

서비스가 Windows NT의 한 프로세스에서 DLL로 실행되는 모든 이유는 별도의 프로세스만큼 느리기 때문입니다.

만약 당신이 더럽혀 졌다면 라이브러리 로딩 전략이 문제라는 것을 알게 될 것입니다.

일반적으로 Unices에서는 공유 라이브러리 (DLL) 코드 세그먼트가 실제로 공유됩니다.

Windows NT는로드 후 라이브러리 코드 세그먼트 (및 실행 코드 세그먼트)를 조작하기 때문에 프로세스별로 DLL 복사본을로드합니다. (데이터는 어디에 있습니까?)

이로 인해 재사용 할 수없는 라이브러리의 코드 세그먼트가 생성됩니다.

따라서 NT 프로세스 생성은 실제로 비용이 많이 듭니다. 그리고 단점은 DLL이 메모리를 크게 절약하지 못하지만 앱 간 종속성 문제가 발생할 가능성이 있다는 것입니다.

때로 공학적으로 물러서서 “이제 정말 짜증나게 설계한다면 어떤 모습일까요?”라고 말하는 것이 좋습니다.

나는 옛날에 꽤 변덕 스러웠던 임베디드 시스템으로 작업했고, 어느 날 그것을보고 마이크로파 캐비티에 전자 장치가있는 캐비티 마그네트론이라는 것을 깨달았습니다. 그 후 우리는 훨씬 더 안정적으로 만들었습니다.


답변

짧은 대답은 “소프트웨어 레이어 및 구성 요소”입니다.

Windows SW 아키텍처에는 Unix에 존재하지 않거나 Unix의 커널 내에서 단순화되고 처리되는 몇 가지 추가 계층 및 구성 요소가 있습니다.

Unix에서 fork와 exec는 커널에 대한 직접 호출입니다.

Windows에서는 커널 API가 직접 사용되지 않고 win32 및 그 위에 특정 기타 구성 요소가 있으므로 프로세스 생성은 추가 계층을 거쳐야하며 새 프로세스가 시작되거나 해당 계층 및 구성 요소에 연결되어야합니다.

꽤 오랫동안 연구자들과 기업들은 막연하게 비슷한 방식으로 유닉스를 분해하려고 시도해 왔습니다. 보통 그들의 실험은 마하 커널을 기반으로합니다 . 잘 알려진 예는 OS X 입니다.. 하지만 매번 시도 할 때마다 너무 느려져서 적어도 부분적으로 커널에 영구적으로 또는 프로덕션 배송을 위해 다시 병합하게됩니다.