私はWindowsのカーネルを熟知しており、Linuxのカーネルについてはそれなりに知っています。
意外に思われるかもしれませんが、類似点の方がずっと多く、違いは少ないです。私がよく言う違いの1つは、LinuxのI/OモデルはUNIXから継承した同期式が基本で、WindowsのI/OモデルはVMSから継承した非同期式が基本であるということです。WindowsのI/Oリクエストの設計は、同期式と非同期式のI/Oを美しく管理できる優れた設計になっています。Linux(及び普通のUNIX)でも非同期のI/Oは可能ですが、そのための統一された仕組みはありません。これは致命的な欠陥ではなく、設計思想の違いですが、個人的には、Windowsの方がアーキテクチャ的に優れた選択だったと思っています。
どちらもスレッドとプロセスをサポートしています(Linuxはタスクという共通の構造を用いていますが)。どちらもページング方式の仮想メモリをサポートしています。どちらもネットワークをサポートしています。どちらもファイルシステムの動的な組み込みが可能です(この機能のインターフェイスは両者で大きく異なっていますが)。
Windowsは膨大な時間と労力をかけて非常に移植性の高いデバイスドライバのモデルを構築しました。デバイスドライバは様々なバージョンのOSやCPUアーキテクチャに対応しており、1つのソースコードで様
私はWindowsのカーネルを熟知しており、Linuxのカーネルについてはそれなりに知っています。
意外に思われるかもしれませんが、類似点の方がずっと多く、違いは少ないです。私がよく言う違いの1つは、LinuxのI/OモデルはUNIXから継承した同期式が基本で、WindowsのI/OモデルはVMSから継承した非同期式が基本であるということです。WindowsのI/Oリクエストの設計は、同期式と非同期式のI/Oを美しく管理できる優れた設計になっています。Linux(及び普通のUNIX)でも非同期のI/Oは可能ですが、そのための統一された仕組みはありません。これは致命的な欠陥ではなく、設計思想の違いですが、個人的には、Windowsの方がアーキテクチャ的に優れた選択だったと思っています。
どちらもスレッドとプロセスをサポートしています(Linuxはタスクという共通の構造を用いていますが)。どちらもページング方式の仮想メモリをサポートしています。どちらもネットワークをサポートしています。どちらもファイルシステムの動的な組み込みが可能です(この機能のインターフェイスは両者で大きく異なっていますが)。
Windowsは膨大な時間と労力をかけて非常に移植性の高いデバイスドライバのモデルを構築しました。デバイスドライバは様々なバージョンのOSやCPUアーキテクチャに対応しており、1つのソースコードで様々なバージョンのWindowsに対応できるドライバを書けます。リッチなプログラミングモデルがあります(周辺バスの仮想メモリのサポート、多重スロット/多重割り込みのデバイス、その他様々な秘密奥義のサポート)。Linuxは歴史的に単発のドライバになっています。一定の構造化はされていますが、私が知る限り、移植性は高くありません。1つのソースコードに統合することもできますが、条件付きコンパイルの嵐で酷いコードになる可能性が高いです。
WindowsのAPIは文字列長付きの16ビットのユニコードを採用しています。Linuxは8ビットのUTFを採用しています。どちらにも批判はあると思いますが、長年C言語で開発してきた私としては、文字列長が組み込まれている方が好きです。NULL終端文字列は良くないと思っています。エラーになりやすいので。でもどちらでも機能します。
WindowsはMS-DOSから受け継いだ変な遺産があります。例えば、MAX_PATH_LENにマニフェスト定数(260)を追加した人がいます。でもWindowsのパスの長さは最長で32,767文字です。文字列の長さを符号なしの16ビットにしたためです。1文字は2バイトです。
Windowsのファイル・ハンドルとLinuxのファイル・ディスクリプタは、使用方法から見れば基本的に同じものです。ファイルはいずれも、バイトやブロックの単位でアクセスされます。
どちらもシステムコールは高速です。どちらも高度なスケジューラを備えています(Linuxは長年に渡り何度もスケジューラを作り直していますが)。信頼性に関して言えば、どちらも非常に堅牢です。Linuxに比べてWindowsは再起動が必要になることが多いとの批判がよくありますが、Windowsのカーネルは運用中の更新に対応しています。システムの再起動が必要になるのは、DLLの更新ができないためのようですが、これはいつも不満に思っています。カーネルモージュールは再起動しなくても更新できるのに、お粗末なユーザーモードのコードが再起動の原因になっているのです。まぁそれはさておき。
WindowsはLinuxのバイナリが動きます(Windowsのバイナリも一部はLinuxで動きますが)。確かに、これは新機能であり、まだベータ版ですが。
結局OSはツールに過ぎません。動けばよいのです。うまく動くのか動かないか。たいていは、非常に高度で大胆なトレードオフの結果でしょう。目の前の問題を解決するのに最適なものを選べばよいです。
John Gwinnerさんのコメント
とても公平な回答をありがとうございました。スレッドやプロセスについて言及されていますね。私は98年にWindowsで高速データ収集システムを開発しました。Windowsはプロセス内のスレッドをうまくサポートしており、少なくとも当時は、Linuxよりもずっと優れていたと思います。大半のLinux開発者は、別のプロセスを呼び出すことでマルチスレッドをする傾向がありますね(訳注:ここでは並列処理という意味であり、スレッド機能を使うという意味ではないようです)。これは過去の遺物であり、もっとうまい方法があるような気がします。知らんけど。
昔はコンテキストスイッチがとても気になっていました。これはCPUから見てコストの高い処理です。高負荷のマシンがあっても、CPU使用率が必ずしも100%ではないことがあります。プログラマーたちは「CPUを使い切っていないので、自分のコードには問題ない」と言ってこの問題を無視するでしょう。
Tony Masonさん(元の投稿者)のコメント
OSの歴史的な理由によります。UNIXやLinuxは元々プロセスのみをサポートており、進化してスレッドをサポートしました。そのため「マルチスレッド」をするには新しいプロセスを作るのがもっとも簡単であり、たいていの場合は、フォークしていました。カトラーのチームが作ったOSが最初からスレッドを考慮した設計になっており、APIもスレッドの使用を推奨する形になっていました。フォークのようなもの(Windowsカーネルの用語でクローン)もありますが、Win32 APIからは使えません。
Linuxでpthread_createのドキュメントをよく読むと、オリジナルの(ユーザーモード(UM)の)スレッド対応の名残が見られます。当時のUMスレッドはシステムコールを1つしか呼べなかったため、カーネルスレッド(Windows NTやSolaris等)と比べて不便でした。Linuxには割と前からカーネルスレッドがありましたが、プログラマーの習慣を変えるのは意外に難しく、今でも使えるフォークに慣れてしまうとそれに固執してしまうのです。
John Gwinnerさんのコメント
まさしく! 全く私の考えている通りです。オープンソースの初期はフォークを多用していましたので、LinuxアプリをWindowsに移植するときは本当にイライラしました。
Unix系OS(Solaris等)やLinuxはハイエンドマシンで動作しており、一般的なパソコンに比べて非常に高性能だったというところが両者の大きな違いだったと思います。別のプロセスにコンテキストスイッチするのに数千クロックの時間がかかる? まぁいいや、と。
80386だったら? そんなパワーはないですから。
Tony Masonさん(元の投稿者)のコメント
旧世代の人間ですみませんが、1980年代に1MBのメモリを搭載した68K系列のSunワークステーションを使っていました。(Solarisのカーネルがスレッドに対応した頃の)1993年当時のワークステーションのほとんどは、Windows NTの最小構成とほぼ同じでした(NT 3.1では最低16MB、NT 3.5では12MBに下がりましたが、非公式ながらどちらも8MBあれば起動して使用可能でした)。Linuxもローエンドのマシンが出自です。なので計算能力の問題ではないでしょう。
私が90年代後半にデバイスドライバの開発を教えていた時、マルチプロセッサの問題について解説しましたが、当時はマルチコアのマシンを誰も持っていない時代であり、笑われていました。Windows NTは最初からマルチコアを考慮した設計になっていました。その10年後にはマルチコアが登場し、逆にシングルコアの時だけに再現する問題について教えないといけなくなりました…。現在はデスクトップパソコンに64コアのCPUを搭載できます。ハードの進化に合わせてOSも進化しないといけません。
従って、システムの根本的な設計に違いがあったと言えます。カトラーとそのチームはこの問題を正しく認識していました。今のLinuxにはカーネルスレッドの機能があり、数多くのハイパフォーマンスコンピューティングで利用されています。フォークも動作しますが、確実にオーバーヘッドが大きいです。
WindowsとLinuxの間には、違いよりも共通点の方がたくさんあります。WindowsとLinuxは、OSが進化してきた過程が異なっているにも関わらず。
John Gwinnerさんのコメント
大筋で同意です。私がメモリマップドで言いたかったのは、メモリマップドが可能か否かという話ではなくて、ローダーが.exeの一部分だけを選んで読み取り、全体を読むことはほとんどなかったということです。これはNTの前からあるもので、Windows 1.Xで既に実装されています。
はい、私もその頃から業界にいる旧世代の人間です。ワークステーションに触れる機会がほとんどありませんでしたが、Oracleと仕事をする頃にはPCがかなり高性能になっていました。
Jean-Yves Landryさんのコメント
WindowsがGUIの大半をカーネルに「密結合」している点に言及されていません。GUIのパフォーマンスを向上させるために採用されました。Windows Vista以降はそれなりに安定していましたが、昔はこれがBSODの原因になっていました。またウイルスの攻撃対象にもなっています。
一方LinuxではGUIは完全にオプションです。カーネルに統合された「カードグラフィックドライバ」がオプションとして存在しています。しかもX-windowシステム(表向きのGUI)はほとんどユーザースペースのプログラムになっています。
Tony Masonさん(元の投稿者)のコメント
カーネル内でGUIをサポートしている部分はwin32k.sysというモジュールに完全に隔離されています。win32k.sysは独自のシステムコールを持ち、システムの他の部分とは独立した形でGDIドライバを管理しています。GDIをカーネル(NT 4.0)に移すという決定は、パフォーマンス向上の目的で実施されたことは確かですが、他にも方法があったかどうかについては私にはわかりませんし、マイクロソフトはユーザーモードから直接グラフィックデバイスを制御できるようにするための様々な仕組みを導入しています。
従って、私はこれを、WindowsがLinuxよりも優れた設計や実装であること示す例として挙げないことにしました。私にはこれが良いことかどうかはっきりしないからです。注目すべき設計であることに間違いありませんが、元の質問は、何が優れているのかという質問でしたので。
Jean-Yves Landryさんのコメント
win32k.sysをカーネル空間に配置するのは良くない設計です。これはサーバなどの目的で使用する際にWindows NTがUnixやLinuxのような信頼性を持つことができない重大な欠陥だと思います。
NT 3.1がリリースされたとき、Windows NTはOS/2のように、win32k.sysサブシステムの大部分をリング2に配置するのではないかと私は思っていました。実際のところ、カトラーがVMSで採用していたRMS(レコードマネージメントシステム)をスーパーバイザモードで実行し、ユーザーモードのプログラムから保護する昔のやり方の方が一貫性がありました。
でもVAXやAlphaと違って、インテルx86でのリングの切り替えはかなりのオーバーヘッドが発生するということをカンファレンスで聞きました。
またVAXはリアルタイム性のあるシステムではないと教わりました。プロセスの生成、ファイルの生成、小さなプログラムのロードなどは遅かったのです。ハイエンドのハードで動くタイムシェアリングシステムなので許容範囲内でしたが…。遅いディスクドライブと4MBしかないメモリを搭載したパソコンでは耐えられませんでした。
Johannes Schneiderさんのコメント
その通り。そしてマイクロソフトはここ数年間にコアOSを深いところまでリファクタリングし、その依存関係を取り除き、全てのサーバー管理機能をPowershellに移行させるということに凄い努力していました(現在のエンタープライズ向け管理者ツールは実際にはPowershellのラッパーに過ぎないと聞いたら驚くのでは!)。
その結果としてNano Server 2016は最小限のコアと拡張コンポーネントだけを搭載したヘッドレスのシステムで、GUIとの依存関係はもはや全くありません(2012年からあるCore Serverとは違うものです。これもヘッドレスでしたが、中身はまだ多少の依存関係が残っていました)。まぁ正直言って、こんな日が来るとは思いもよりませんでしたね…:)。
この質問は技術的な機能の優劣に関する質問と捉えられますが、その奥にはもっと根本的な問題があると思います。それは開発体制の違いです。プロプライエタリーな一社集中開発とオープンソースな分散開発の差です。当然どちらがいいという話ではなく、双方利点と欠点があります。
OSの範囲をカーネルと捉えるか、ドライバやライブラリまで含めたシステムと捉えるかでも異なります。カーネルの役割をファイルシステム、外部/プロセス間通信、プロセス/スレッド管理、メモリ管理、と捉えれば、この二つのOSには大きな差はないと思います。どなたかがご指摘されていたようにファイルシステムのセキュリティ周りはWindowsに分があると思いますが、基本的な機能では優劣は大きくないように思えます。
ドライバやライブラリを含めたシステムで考えると、クローズとオープンの開発体制の差が如実に現れます。様々なディストロに発散して統一性のないLinuxと狭い範囲で安定したWindows。その分、先進的な機能はLinuxの取り込みが早くWindowsはゆっくり進化している部分が多いように見えます。どちらもカーネルとしては十分な完成の域にあるのに、商用アプリ開発者があまりLinuxアプリを作成しないのは、この多様性がビジネス拡大の妨げになっているからです。一方でWindowsはクローズですが、非常に手厚いbackward compatibilit
この質問は技術的な機能の優劣に関する質問と捉えられますが、その奥にはもっと根本的な問題があると思います。それは開発体制の違いです。プロプライエタリーな一社集中開発とオープンソースな分散開発の差です。当然どちらがいいという話ではなく、双方利点と欠点があります。
OSの範囲をカーネルと捉えるか、ドライバやライブラリまで含めたシステムと捉えるかでも異なります。カーネルの役割をファイルシステム、外部/プロセス間通信、プロセス/スレッド管理、メモリ管理、と捉えれば、この二つのOSには大きな差はないと思います。どなたかがご指摘されていたようにファイルシステムのセキュリティ周りはWindowsに分があると思いますが、基本的な機能では優劣は大きくないように思えます。
ドライバやライブラリを含めたシステムで考えると、クローズとオープンの開発体制の差が如実に現れます。様々なディストロに発散して統一性のないLinuxと狭い範囲で安定したWindows。その分、先進的な機能はLinuxの取り込みが早くWindowsはゆっくり進化している部分が多いように見えます。どちらもカーネルとしては十分な完成の域にあるのに、商用アプリ開発者があまりLinuxアプリを作成しないのは、この多様性がビジネス拡大の妨げになっているからです。一方でWindowsはクローズですが、非常に手厚いbackward compatibilityを持っています。これも商用アプリ開発の動機づけになります。
如何に商用アプリを増やしていくか、もOSの大事な設計要素の一つと捉えることができると思います。そしてこの部分ではWindowsが圧倒的に優位です。Linuxはその開発体制故に、先進性と自分好みの機能の取り込みに長けている分この部分が弱く、結果として広がりに欠けてしまった側面があります。
ハードウェアの進化が激しく、一昔前だったら重くて使い物にならなかった設計のアプリがどんどん動作可能になっていくこの世界で、カーネル周りの純粋に技術的な優劣の意味は薄れているのではないかと思います。そこでの効率の差など、パソコンが一世代進めばすぐにひっくり返ってしまいます。
オープンの世界でもかってのGNUや今のpythonのようにある程度統一性をコントロールするソフト開発は可能です。それに対してLinuxは別の道を選びました。多様性、先進性に富み、しかしバラバラ、これがLinuxのOSとしての「設計の基本」です。それがいいのか悪いのかはさておき、商用ソフトウェア開発者が使いたいと思う魅力は薄いOSだと感じます。
明らかに優れている点は
- ファイルアクセス権限管理(Linuxでもaclは使えますが..)
- ユーザー管理(Linuxでも高度な管理は追加機能として可能ですが..)
- 監査機能(SELinuxが似たような機能ですが..)
- 機能設定集中管理
- 強固な認証(Kerberosベース。勿論Linuxでも使えますが..)
- 印刷管理(LinuxでもCUPsが使えますが、Windowsとは次元が異なります)
ビジネスで利用する場合に必要な管理機能は圧倒的に強力で使い易いです。
この辺りのビジネスで必要となる管理機能がActiveDirectoryで統合管理できます。大規模システムの管理者なら経営陣が「WindowsからLinuxへ全面移行します!」なんて言い出したら匙を投げ出したくなる人が続出でしょう、WindowsとLinuxの両方を知っている管理者だったとしても。
注) テキトーな管理をしている組織ならWindowsでもLinuxでも変わらないです。しっかり管理している組織の場合です。
Windows のIO完了ポートに尽きますね。最近Linuxでio_uringが追加されましたが、IO完了ポートはプールされたマルチスレッドをいとも簡単に利用させてくれます。これは凄いと思います。
自己責任で解決するLinux、お金で解決できるWindows。
とか書くと、サポートの切れたWindowsも自己責任なので、本質的にはLinuxなのかもしれません(違います)
Windowsは、GUIに関してはLinuxよりも優れていますが、それを裏返しにいうと、Programが大きくなりメモリーやディスクを多く消費して動作が遅いということになります。GUIが不要でプロしか使わないサーバー分野では、Linuxの方が優れています。
また、OSがすべてOSSで公開されていることからプログラミングにも便利です。
OSの設計と、利用者の使い勝手とはほぼ同じではないですか?