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


101

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

답변:


68

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

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

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

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

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


8
Fork 다음에 항상 exec ()가 오는 것은 아니며 사람들은 fork () 만 신경 쓰고 있습니다. Apache 1.3은 Linux에서 fork () (exec없이)를 사용하고 Windows에서는 스레드를 사용합니다. 많은 경우 프로세스가 필요하기 전에 분기되어 풀에 유지되는 경우에도 마찬가지입니다.
Blaisorblade

5
물론 당신이 설명하는 'just call exec'시나리오를 위해 설계된 'vfork'명령을 잊지 마십시오.
Chris Huang-Leaver

4
이로 인해 심각하게 영향을받는 또 다른 종류의 소프트웨어 는 여러 프로세스의 조정을 포함하는 모든 종류의 쉘 스크립팅입니다. 예를 들어 Cygwin 내부의 Bash 스크립팅은 이로 인해 큰 어려움을 겪습니다. 파이프 라인에서 많은 sed, awk 및 grep을 생성하는 쉘 루프를 고려하십시오. 모든 명령은 프로세스를 생성하고 모든 파이프는 해당 서브 쉘에 서브 쉘과 새 프로세스를 생성합니다. 유닉스는 이런 종류의 사용을 염두에두고 설계 되었기 때문에 빠른 프로세스 생성이 표준으로 남아 있습니다.
Dan Molding

5
-1. 프로세스 생성 속도를 늦추는 호환성 문제로 가득 찬 잘못 설계된 운영 체제에서 제대로 실행되지 않기 때문에 소프트웨어가 '잘 이식되지 않았다'는 주장은 말도 안됩니다.
Miles Rout

6
@MilesRout 포팅의 목표는 해당 시스템의 강점과 단점을 염두에두고 새로운 대상 시스템에서 실행되도록 소프트웨어를 수정하는 것입니다. 포팅 된 소프트웨어의 성능 저조한 것은 운영 체제가 제공하는 장애물에 관계없이 제대로 포팅 된 소프트웨어입니다.
Dizzyspiral

28

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

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


22
이 주장은 당신이 정말로 포크 할 때만 유효합니다. 새 프로세스를 시작하는 경우 Unix에서 여전히 fork 및 exec를 수행해야합니다. Windows와 Unix 모두 쓰기시 복사 기능이 있습니다. 앱의 두 번째 복사본을 실행하면 Windows는로드 된 EXE를 확실히 재사용합니다. 나는 당신의 설명이 정확하지 않다고 생각합니다.
Joel Spolsky

1
exec () 및 fork ()에 대한 추가 정보 vipinkrsahu.blogspot.com/search/label/system%20programming
webkul

내 대답에 성능 데이터를 추가했습니다. stackoverflow.com/a/51396188/537980 더 빠르다는 것을 알 수 있습니다.
ctrl-alt-delor jul.

25

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 관련 항목은 전혀 관여하지 않습니다.


16

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

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


2
마지막 요점에 대해 : fork ()는 CreateProcess ()와 교환 할 수 없지만 Windows에서 더 많은 유연성을 제공하기 때문에 fork ()를 구현해야한다고 말할 수도 있습니다.
Blaisorblade

아, 동사 To Bee.
acib708

그러나 Linux의 fork + exec는 MS-Windows의 CreateThread보다 빠릅니다. 그리고 Linux는 자체적으로 포크를 더 빠르게 할 수 있습니다. 그러나 비교하면 MS가 느립니다.
CTRL-ALT-delor

13

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

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

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

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


9

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

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

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

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

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

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

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

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

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

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


3
DLL이 기본 주소에서로드되는 한 코드 세그먼트를 재사용 할 수 있습니다. 일반적으로 프로세스에로드되지만 ASLR에서는 작동하지 않는 모든 DLL에 대해 충돌하지 않는 기본 주소를 설정해야합니다.
Mike Dimmick

모든 DLL을 리베이스하는 도구가 있습니까? ASLR로 무엇을하는지 잘 모르겠습니다.
Zan Lynx

3
코드 섹션 공유는 ASLR 지원 시스템에서도 작동합니다.
Johannes Passing

@MikeDimmick 그래서 DLL을 만드는 모든 사람들은 충돌이 없는지 확인하기 위해 협력해야합니다. 아니면로드하기 전에 시스템 수준에서 모두 패치합니까?
ctrl-alt-delor

9

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

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

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

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

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


레이어가 반드시 속도를 늦출 필요는 없습니다. 저는 C로 많은 레이어가있는 장치 드라이버를 작성했습니다. 깔끔한 코드, 읽기 쉬운 프로그래밍, 읽기 쉽습니다. 레이어없이 고도로 최적화 된 어셈블러로 작성된 버전보다 약간 더 빠릅니다.
ctrl-alt-delor jul.

아이러니는 NT가 큰 커널 (안 마이크로 커널)라는 것이다
CTRL-ALT-delor

2

일부 답변에서 MS-Windows에 대한 정당화가있는 것 같습니다.

  • “NT 커널과 Win32는 같은 것이 아닙니다. NT 커널로 프로그래밍하면 그렇게 나쁘지 않습니다.”— 맞습니다.하지만 Posix 하위 시스템을 작성하지 않는 한 누가 신경을 쓰겠습니까? win32에 글을 쓸 것입니다.
  • "포크를 ProcessCreate와 비교하는 것은 공정하지 않습니다. 서로 다른 작업을 수행하고 Windows에는 포크가 없기 때문입니다."— 사실입니다. 그러나 포크는 프로세스 격리 (예 : 웹 브라우저의 각 탭이 다른 프로세스에서 실행 됨)와 같은 많은 사용 사례가 있기 때문에 포크도 비교할 것입니다.

이제 사실을 살펴 보겠습니다. 성능의 차이는 무엇입니까?

http://www.bitsnbites.eu/benchmarking-os-primitives/ 에서 요약 된 데이터 .
편견이 불가피하기 때문에 요약하면 대부분의 테스트 i7 8 코어 3.2GHz 에서 MS-Windows 하드웨어를 선호했습니다
. Gnu / Linux를 실행하는 Raspberry-Pi 제외

Gnu / Linux, Apple-Mac 및 Microsoft의 Windows에서 다양한 기본 작업 비교 (작을수록 좋음)

MS-Windows 프로세스 생성과 Linux 비교

참고 : Linux에서는 forkMS-Window의 기본 방법보다 빠릅니다 CreateThread.

프로세스 생성 유형 작업에 대한 숫자 (차트에서 Linux에 대한 값을보기가 어렵 기 때문).

속도 순으로 가장 빠른 것에서 가장 느린 것 (숫자는 시간, 작은 것이 더 좋음)입니다.

  • 리눅스 CreateThread 12
  • 맥 CreateThread 15
  • 리눅스 포크 19
  • Windows CreateThread 25
  • Linux CreateProcess (fork + exec) 45
  • 맥 포크 105
  • Mac CreateProcess (fork + exec) 453
  • Raspberry-Pi CreateProcess (fork + exec) 501
  • Windows CreateProcess 787
  • 바이러스 스캐너 2850을 사용하는 Windows CreateProcess
  • Windows Fork (CreateProcess + fixup으로 시뮬레이션)가 2850 이상

다른 측정을위한 숫자

  • 파일 생성.
    • Linux 13
    • 맥 113
    • Windows 225
    • Raspberry-Pi (슬로우 SD 카드 포함) 241
    • 수비수 및 바이러스 스캐너 등이있는 Windows 12950
  • 메모리 할당
    • 리눅스 79
    • 윈도우 93
    • 맥 152

1

그 외에도 Win 시스템에서 바이러스 백신 소프트웨어가 CreateProcess 중에 시작된다는 사실이 있습니다. 일반적으로 가장 느린 속도입니다.


1
네, 그것은 가장 큰 것이지만 유일하게 중요한 감속은 아닙니다.
ctrl-alt-delor

1

또한 Windows의 보안 모델이 Unix 기반 OS보다 훨씬 더 복잡하여 프로세스 생성 중에 많은 오버 헤드가 추가된다는 점도 주목할 가치가 있습니다. Windows에서 멀티 스레딩이 멀티 프로세싱보다 선호되는 또 다른 이유입니다.


1
더 복잡한 보안 모델이 더 안전 할 것으로 기대합니다. 그러나 사실은 그렇지 않다는 것을 보여줍니다.
Lie Ryan

4
SELinux는 또한 매우 복잡한 보안 모델이며 상당한 오버 헤드를 부과하지 않습니다.fork()
Spudd86 2011 년

6
@LieRyan, 소프트웨어 설계 (내 경험상)에서 더 복잡하다는 것은 매우 드물게 더 안전하다는 것을 의미합니다.
Woodrow Douglass 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.