回答:
mweerden:NTは最初からマルチユーザー向けに設計されているため、これは実際には理由ではありません。ただし、Unixとは対照的に、NTはマルチプロセッシングよりもマルチスレッド化を優先するため、プロセスの作成はUNIXでの場合よりもUNIXでの場合ほど重要ではありません。
Rob、COWを使用するとフォークが比較的安価であることは事実ですが、実際のところ、フォークのほとんどはexecに続いています。また、幹部はすべての画像もロードする必要があります。したがって、フォークのパフォーマンスを議論することは真実の一部にすぎません。
プロセス作成の速度について説明するときは、NTとWindows / Win32を区別することをお勧めします。NT(つまり、カーネル自体)に関する限り、プロセスの作成(NtCreateProcess)とスレッドの作成(NtCreateThread)は、平均的なUnixのように大幅に遅いとは思いません。もう少し進んでいるかもしれませんが、ここではパフォーマンスの違いの主な理由はわかりません。
ただし、Win32を見ると、プロセスの作成にかなりのオーバーヘッドが追加されていることがわかります。1つは、LPCを含むプロセスの作成についてCSRSSに通知する必要があることです。少なくともkernel32を追加でロードする必要があり、プロセスが本格的なWin32プロセスと見なされる前に、いくつかの追加の簿記作業項目を実行する必要があります。そして、マニフェストの解析、画像に互換性シムが必要かどうかの確認、ソフトウェア制限ポリシーが適用されるかどうかの確認によって課される追加のオーバーヘッドすべてを忘れないでください、yada yada。
とはいえ、プロセス、VAスペース、および初期スレッドの生の作成に加えて、実行する必要があるこれらすべての小さなことの合計の全体的な減速がわかります。しかし、冒頭で述べたように、マルチタスクよりもマルチスレッディングの方が有利であるため、この追加の費用によって深刻な影響を受けるソフトウェアは、移植が不十分なUnixソフトウェアだけです。この状況は、ChromeやIE8などのソフトウェアが突然マルチプロセッシングの利点を再発見し、頻繁にプロセスを起動および破棄するようになると変化しますが...
Unixには、現在のプロセスを2つに「分割」する「fork」システムコールがあり、最初のプロセスと同じ2番目のプロセスを提供します(forkコールからの戻りを法として)。新しいプロセスのアドレススペースはすでに稼働しているため、Windowsで「CreateProcess」を呼び出して、exeイメージや関連するdllなどをロードするよりも安価です。
フォークの場合、OSは両方の新しいプロセスに関連付けられたメモリページに「コピーオンライト」セマンティクスを使用して、それぞれが後で変更するページの独自のコピーを確実に取得できるようにします。
JPの発言に追加すると、ほとんどのオーバーヘッドは、プロセスのWin32スタートアップに属します。
Windows NTカーネルは、実際にはCOWフォークをサポートしています。SFU(MicrosoftのWindows用UNIX環境)は、それらを使用します。ただし、Win32はフォークをサポートしていません。SFUプロセスはWin32プロセスではありません。SFUはWin32に直交しています。どちらも同じカーネル上に構築された環境サブシステムです。
へのアウトプロセスLPC呼び出しに加えて、CSRSS
XP以降では、アプリケーション互換性エンジンへのアウトプロセスコールがあり、アプリケーション互換性データベースでプログラムを検索します。この手順により、パフォーマンス上の理由から、MicrosoftがWS2003の互換性エンジンを無効にするグループポリシーオプションを提供するのに十分なオーバーヘッドが発生します。
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スレッドライブラリのようなものがあります。しかし、長い間、UNIXの世界で作業を「委任」する唯一の方法は、fork()を使用することでした(そして、それは多くの状況で依然として好まれています)。例:ある種のソケットサーバー
socket_accept() フォーク() もし(子供) handleRequest() そうしないと goOnBeingParent()したがって、フォークの実装は高速である必要があり、多くの最適化が時間とともに実装されています。マイクロソフトは、新しいプロセスを作成したり、プロセス間通信を使用したりする代わりに、CreateThreadまたはファイバーさえも承認しました。CreateProcessとforkを交換することはできないため、それらを比較することは「公平」ではないと思います。fork / execをCreateProcessと比較する方がおそらく適切です。
この問題の鍵は、両方のシステムの歴史的な使用法だと思います。Windows(およびその前のDOS)は、もともとパーソナルコンピュータのシングルユーザーシステムでした。そのため、これらのシステムは通常、常に多くのプロセスを作成する必要はありません。(非常に)簡単に言うと、プロセスは、この1人の孤独なユーザーが要求したときにのみ作成されます(そして、私たち人間は、比較的高速に動作しません)。
Unixベースのシステムは、もともとマルチユーザーシステムとサーバーでした。特に後者の場合、特定のジョブを処理するためにプロセスを分割するプロセス(たとえば、メールまたはhttpデーモン)を使用することは珍しくありません(たとえば、1つの着信接続を処理します)。これを行う際の重要な要素は安価なfork
方法です(Rob Walker(47865)が言及したように、最初は新しく作成されたプロセスに同じメモリを使用します)。これは、新しいプロセスが必要なすべての情報をすぐに保持するので非常に便利です。
少なくとも歴史的には、UNIXベースのシステムが高速なプロセスを作成する必要性は、Windowsシステムの場合よりもはるかに大きいことは明らかです。Unixベースのシステムは依然として非常にプロセス指向であり、Windowsはその歴史上、おそらくスレッド指向である(スレッドは応答性の高いアプリケーションの作成に役立つ)ため、これは依然として当てはまると思います。
免責事項:私は決してこの問題の専門家ではないので、私がそれを間違えた場合、私を許してください。
ええと、進行中の正当化の多くの「それはこの方法の方がいい」のようです。
人々は「Showstopper」を読むことから利益を得ることができると思います。Windows NTの開発に関する本。
サービスがWindows NTの1つのプロセスでDLLとして実行される理由は、それらが個別のプロセスとしては遅すぎるためです。
落ちて汚い場合は、ライブラリのロード戦略に問題があることがわかります。
Unices(一般的に)では、共有ライブラリ(DLL)のコードセグメントが実際に共有されます。
Windows NTは、ロード後にライブラリコードセグメント(および実行可能コードセグメント)を操作するため、プロセスごとにDLLのコピーをロードします。(あなたのデータはどこにあると言いますか?)
これにより、再利用できないライブラリのコードセグメントが生成されます。
したがって、NTプロセスの作成は、実際にはかなり高価です。そしてマイナス面としては、DLLがメモリを大幅に節約することはできませんが、アプリ間の依存関係の問題が発生する可能性があります。
時々、エンジニアリングに戻り、「今、本当にこれを吸うようにこれを設計しようとすると、それはどのように見えるでしょうか?」
むかしむかしむかしむかれた組み込みシステムを使用していたところ、ある日それを見て、マイクロ波空洞に電子機器を備えた空洞マグネトロンであることに気付きました。その後、私たちはそれをはるかに安定させました(そして電子レンジのようにはなりませんでした)。
Windows SWアーキテクチャには、Unixには存在しないか、単純化されてUnixのカーネル内で処理される追加のレイヤーとコンポーネントがいくつかあります。
Unixでは、forkとexecはカーネルへの直接の呼び出しです。
Windowsでは、カーネルAPIは直接使用されず、その上にwin32と他の特定のコンポーネントがあるため、プロセスの作成は追加のレイヤーを通過し、新しいプロセスが起動するか、それらのレイヤーとコンポーネントに接続する必要があります。
かなり長い間、研究者や企業は漠然と同様の方法でUnixを解体しようとしましたが、通常は実験をMachカーネルに基づいています。よく知られている例はOS Xです。しかし、彼らが試みるたびに非常に遅くなり、少なくとも部分的にカーネルに部分的にマージすることになります。これは、永続的または製品出荷のためです。
いくつかの回答でMS-Windowsの正当化があるように見えるので、例えば
http://www.bitsnbites.eu/benchmarking-os-primitives/から要約されたデータ。
バイアスは避けられないため、要約すると、ほとんどのテストではi7 8コア3.2GHz のMS-Windows ハードウェアを優先しました
。Gnu / Linuxを実行するRaspberry-Piを除く
注:Linuxでは、fork
MS-Windowの推奨される方法よりも高速ですCreateThread
。
速度の速いものから遅いものへ(数値は時間であり、小さいほど良い)。
これらすべてに加えて、Winマシンでは、おそらくウイルス対策ソフトウェアがCreateProcess中に起動するという事実があります...これは通常、最大のスローダウンです。
また、WindowsのセキュリティモデルはUNIXベースのOSよりもはるかに複雑であるため、プロセスの作成中に多くのオーバーヘッドが発生することにも注意してください。Windowsのマルチプロセッシングよりもマルチスレッド化が好まれるもう1つの理由。
fork()