私はLinuxカーネルメーリングリストのエチケットの文脈でこれについて考え始めました。世界で最も有名で最も成功し、重要なフリーソフトウェアプロジェクトであるLinuxカーネルは、幅広い関心を集めてきました。このプロジェクトの創設者でありリーダーであるLinus Torvaldsについては、ここで紹介する必要はありません。
Linusは時々LKMLに対する彼の発言で物議を醸すことがあります。彼自身が認めたところによると、これらの炎はしばしばユーザー空間を破壊することに関連しています。これは私の質問につながります。
ユーザー空間を破壊するのがなぜ悪いのかという歴史的な視点を得ることができますか?私が知っているのは、ユーザースペースを破るためにアプリケーションレベルで修正する必要がありますが、カーネルコードが改善された場合は悪いでしょうか?
私が理解したのは、Linusが述べたポリシーは、何よりもコード品質を含むユーザースペースを破壊しないことです。これはなぜそんなに重要なのでしょうか?この方針の長所と短所は何ですか?
(明らかに、そのような政策を継続的に適用することにはいくつかの欠点があります。湾の道を行きました。
答え1
その理由は歴史的ではなく実際的です。 Linuxカーネルの上で実行される多数のプログラムがあります。カーネルインタフェースがこれらのプログラムを破壊する場合、誰もがそのプログラムをアップグレードする必要があります。
今、ほとんどのプログラムは実際にカーネルインターフェース(システムコール)、しかしインターフェイスのみC標準ライブラリ(氏包装紙システムコールの周り)。ああ、ところでどの標準ライブラリですか?グリッケ? uClibC?フードライブラリ?バイオニック?無実?など。
しかし、オペレーティングシステム固有のサービスを実装し、標準ライブラリによって公開されないカーネルインタフェースに依存するプログラムもたくさんあります。 (Linuxでは、これらの多くは以下を介して行われます。/proc
そして/sys
.)
その後、静的にコンパイルされたバイナリがあります。カーネルのアップグレードによってそれらの1つがハングした場合、唯一の回避策はそのエントリを再コンパイルすることです。ソースコードがある場合:Linuxは独自のソフトウェアもサポートしています。
ソースが利用可能であっても、すべての情報を収集するのは痛いかもしれません。特に、ハードウェアのバグを修正するためにカーネルをアップグレードする場合は、さらにそうです。人々はハードウェアサポートを必要とするので、システムの残りの部分から独立してカーネルをアップグレードすることがよくあります。内部にリヌス・トバルズの言葉:
ユーザープログラムを壊すことは許されません。 (...)私たちは、人々が長年にわたって古いバイナリを使用してきたことを知っています。あなたは私たちを信頼できます。
そのも説明したこれを強力なルールにする1つは、依存関係の地獄を避けることです。依存関係地獄は、新しいカーネルが機能するために他のプログラムをアップグレードする必要があるだけでなく、すべてがいくつかのバージョンに依存するため、他のプログラムをアップグレードしてからアップグレードする必要があります。すべて。
それ一部明確に定義された一方向の依存関係がある可能性があります。悲しいが時には避けられないことでもあります。 (…)悪いことは、双方向依存性があるということです。ユーザー空間のHALコードが新しいカーネルに依存している場合は問題ありません。しかし、ユーザーはこのコードが「今週のカーネル」ではなく「過去数ヶ月のカーネル」になることを望むと思います。
ただし、双方向の依存関係があると問題が発生します。これは同時にアップグレードする必要があることを意味し、これは許容できません。これはユーザーにとっては残念ですが、より重要なのは開発者にとっては悪いことです。これは、「エラーが発生しました」と言うことができない、または二等分または同様の種類の操作で範囲を絞り込む試みなどの操作を実行できないためです。
ユーザー空間では、これらの相互依存関係は通常、異なるライブラリバージョンを維持することで解決されますが、1つのカーネルしか実行できないため、カーネルで実行したいすべてをサポートする必要があります。
公式、
[システムコールステートメントの安定]以前のバージョンとの互換性は少なくとも2年間保証されています。
しかし実際には
ほとんどのインターフェイス(システムコールなど)は変更されず、常に使用できます。
./sys
/proc
/sys
つまり、
ユーザースペースを破るには、アプリケーションレベルで変更が必要です。
コアが1つだけで、システムの残りの部分とは無関係にアップグレードしようとしているので、これはうまくいきません。しかし、複雑な相互依存性を持つ多くのアプリケーションがあります。数百万の異なる設定で何千ものアプリケーションを最新の状態に保つよりも、カーネルを安定して維持する方が簡単です。
答え2
すべての相互依存システムには、基本的に2つのオプションがあります。抽象化と統合。 (意図的に技術的な用語を使用しません。)抽象化は、APIを呼び出すときにAPIの後のコードを変更する可能性がありますが、結果は常に同じであることを意味します。たとえば、呼び出すときにfs.open()
それがネットワークドライブであるか、SSDであるか、ハードドライブであるかを問わず、常に操作を実行するために使用できるオープンファイル記述子を取得します。 「統合」の目的は、方法が変わっても作業を実行する「最良の」方法を提供することです。たとえば、ネットワーク共有でファイルを開くことは、ディスクでファイルを開くのとは異なる場合があります。どちらの方法も、最新のLinuxデスクトップで広く使用されています。
開発者の観点からは、「すべてのバージョンで動作」または「特定のバージョンで動作」の問題です。 OpenGLは良い例です。ほとんどのゲームは特定のバージョンのOpenGLを使用するように設定されています。ソースからコンパイルしても構いません。 OpenGL 1.1を使用してゲームを作成し、3.xで実行しようとすると、良い経験はありません。一方、一部の呼び出しは関係なく機能すると予想されます。たとえば、fs.open()
私が使用しているカーネルバージョンに気にしたくないと言いたいと思います。私はファイル記述子だけが欲しい。
各アプローチには利点があります。統合は、以前のバージョンとの互換性を犠牲にして「最新」機能を提供します。抽象化は「最新の」呼び出しに安定性を提供しますが。しかし、これが可能性ではなく優先順位の問題であることは注目に値します。
一般の観点から見ると、実際に妥当な理由がない場合は、複雑なシステムでは抽象化が常に優れています。たとえば、fs.open()
カーネルのバージョンによって状況がどのように異なるかを想像してみてください。これにより、単純なファイルシステム対話ライブラリは、数百の異なる「ファイルを開く」方法(またはブロック)を維持する必要があります。新しいカーネルバージョンが出たら、「アップグレード」することはできず、使用しているすべてのソフトウェアをテストする必要があります。カーネル6.2.2(偽)はテキストエディタを破損する可能性があります。
いくつかの実際のケースでは、OSXはユーザー空間の破壊に気を配らない傾向があります。彼らの目標は、「抽象化」ではなく「統合」をより頻繁に行うことです。すべての主要なオペレーティングシステムの更新ごとに問題が発生します。これは、あるアプローチが他のアプローチよりも優れているという意味ではありません。これは選択とデザインの決定です。
結論は、Linuxエコシステムは、個人やグループが余暇に貢献したり、ツールが役に立つので、貢献する素晴らしいオープンソースプロジェクトでいっぱいです。これを念頭に置いて、一度楽しさがなくなり、PIAになり始めると、開発者は別の場所に行きます。
たとえば、にパッチを送信しましたBuildNotify.py
。私は利他的ではなく、このツールを使用して機能したいからです。簡単なのでここにパッチがあります。複雑だったり面倒だったら使わないでBuildNotify.py
他を探してみました。カーネルが更新されるたびにテキストエディタがクラッシュした場合は、他のオペレーティングシステムを使用します。コミュニティへの私の貢献(どんなに小さくても)は持続するか存在しません。
それで、デザインの決定は、システムコールを抽象化して、これを行うときにfs.open()
正しく機能するようにすることでした。これは、fs.open
感染症が発生した後も長く続くことを意味します。fs.open2()
歴史的に、これはPOSIXシステムの全体的な目標でした。 「これは一連の呼び出しと期待される戻り値であり、移植性の理由でもう一度その間の値を把握します。」 Linusがこの方法を選んだ理由は彼の心の中にあり、あなたは彼に正しい理由を尋ねなければなりません。しかし、私は複雑なシステムの統合ではなく抽象化を選択します。
答え3
これはデザインの決定と選択です。 Linusは非常にまれで、特別な状況(セキュリティ関連など)を除いて、カーネルの変更によってアプリケーションが中断されないことをユーザースペース開発者に確信させることができるようにしたいと考えています。
利点は、ユーザー空間開発者が、ランダムで気まぐれな理由で、新しいカーネルで突然コードが破損していることを発見できないことです。
欠点は、カーネルが古いコード、古いシステムコールなどを永遠に(または少なくとも有効寿命以上に)維持する必要があることです。