Unix/Linuxフォークの隠れたオーバーヘッド

Unix/Linuxフォークの隠れたオーバーヘッド

1. フォークの起源

フォークのアイデアは、UNIX が登場する数年前、つまり PDP-7 上の UNIX の最初のバージョンが登場する 6 年前の 1963 年頃に登場しました。
1963 年、コンピューター科学者のメルビン・コンウェイ (コンウェイの法則で知られる) が、フォークのアイデアを正式に提案する論文を書きました。
フォークのアイデアはもともとマルチプロセッサ並列ソリューションとして Conway によって提案されたもので、非常に興味深いアイデアです。つまり、フォークのアイデアはフローチャートから生まれます。

一般的なフローチャートを見てみましょう。

フローチャートの分岐部分、フォークがとても鮮明ですね。

フローチャート上の分岐点から分岐する各分岐は、並列処理の前提となる論理的に独立していることは明らかです。したがって、異なる処理プロセスという形で表現できます。当時の表現は単に「プロセス」という用語であり、現代のオペレーティングシステムの意味での「プロセス」の概念ではありませんでした。

結合同期ポイントは、何らかの理由で複数の並列プロセスを同期する必要があるポイント、つまり複数の並列プロセスが収束するポイントです。現在でも、マルチスレッド プログラミングでは、この点は結合と呼ばれています。たとえば、Java Thread の join メソッドや、pthread ライブラリの pthread_join 関数などです。

広義では、結合はクリティカルセクションなど、シリアルに通過する必要があるポイントも指します。結合ポイントの数を減らすと、並列効率が向上します。

Conway の論文にあるフォークの元の図を見てみましょう。

この論文におけるコンウェイのもう一つの革新は、処理プロセス(後のオペレーティングシステムにおけるプロセスの概念)とプロセスを実行するプロセッサ(つまりCPUコア)を分離し、スケジュール層を抽象化したことである。

一般的な考え方は、「システム内のアクティブなプロセッサの数が、プロセッサの総数と並列処理プロセスの数の最小値である限り」です。これは、スケジューラが、マルチプロセッサ システム内のすべてのプロセッサとシステム内のすべての処理プロセスを、それぞれ統合されたリソース プールとコンシューマーとして扱い、統合されたスケジューリングを実行できることを意味します。

UNIX が fork を導入した後、このマルチプロセッサ並列設計の概念は UNIX の中核に深く根付きました。このアイデアは最終的に UNIX に、そしてその後の Linux にも影響を与え、現在に至っています。
關于這個設計思想為什么可以影響UNIX這么久,我想和Conway本人的“Conway's law”不無關系,在這個law中,他提到:Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure.

2. 初期のUNIXオーバーレイ技術

次に、UNIX フォークの別のコンテキストを見てみましょう。1969 年のオリジナルの UNIX は、今では非常に奇妙に思える方法で動作していました。

一般的な情報は、比較的「新しい」バージョンである UNIX v6 から始まります。そのため、元の UNIX がどのようなものだったかを知っている人はほとんどいません。 1970 年に PDP-7 上で動作していた UNIX のソース コードも参照できるのは fork 導入後のバージョンであり、それ以前のオリジナル バージョンはほぼ見つけることができません (当時の UNIX は UNIX と呼ばれていなかったと言う人もいるかもしれませんが、誰が気にするでしょうか...)。

オリジナルの UNIX は、各端末に 1 つずつ属する 2 つのシェル プロセスのみを持つタイムシェアリング システムでした。

分時系統最初并不是基于進程分時的,那時根本還沒有完整的進程的概念,分時系統是針對終端分時的,而操作員坐在終端前,為了讓每個操作員在操作過程中感覺上是在獨占機器資源,每個終端享受一段時間的時間片,在該時間片內,該終端前的操作員完全享受機器,但是為了公平,超過了時間片,時間片就要給另一個終端。

以上です。タイムシェアリング機能を反映するために、オリジナルの UNIX では最低 2 つの端末が実装されました。オリジナルの UNIX には fork も exec もなく、複数プロセスの概念さえなかったことに注意してください。タイムシェアリングを実現するために、システムには 2 つの単純なシェル プロセスしかありませんでした。

実際、オリジナルの UNIX では、すべてのプロセスを保持するために 2 つの要素のみを持つテーブルが使用されていました (明らかに、これはおかしく見えます...)。もちろん、ここでの「テーブル」の概念も抽象的で単純な概念です。当時のシステムは PDP-7 アセンブリで記述されており、その後 C 言語のデータ構造は存在しなかったためです。

ここで、ターミナルの 1 つでシェル プロセスがどのように機能するかを検討します。すぐに疑問が生じます。このシェル プロセスは他のコマンド プログラムをどのように実行するのでしょうか? ?

システムが最大 2 つのプロセスしか処理できず、端末にシェル プロセスが 1 つしかない場合、端末のシェル プロセスは他のコマンド プログラムを実行するときに何を行うべきでしょうか。この質問については少し考える必要があります...

注意: 1969 年の最初のバージョンの UNIX を現代の視点で評価しないでください。現代の視点では、プログラムを実行すると新しいプロセスが生成されます。明らかに、これは最初のバージョンの UNIX では正しくありません。

答えは、新しいプロセスを作成する必要はまったくないということです。コマンド プログラム コードをメモリにロードし、シェル プロセス コードを上書きするだけです。コマンドが実行されると、シェル コードがコマンド プログラム コードを上書きします。単一の端末の場合、システムは実際には次の上書きループを実行し続けます (論文のプロセス制御セクションより)。

しかし、これは UNIX に fork が導入される前の話です。端末には常に同じプロセスが存在します。シェル コードを実行する場合もあれば、特定のコマンド プログラムのコードを実行する場合もあります。以下はオーバーレイ プログラムの構造です (図は「FreeBSD オペレーティング システムの設計と実装」という書籍から引用)。

ただし、当時、このロジックはまだ exec システム コールにカプセル化されておらず、これらはすべて各プロセスによって明示的に実行されていました。

  • シェルがコマンド プログラムを実行するには、シェル自体がディスク IO を実行してコマンド プログラムをロードし、シェル自身を上書きします。
  • コマンド プログラムの実行が終了すると、exit は内部ディスク IO を呼び出してシェル プログラムをロードします。

exec ロジックはシェル プログラムの一部であり、すべてのコマンド プログラムで使用されるため、exit 呼び出しにもカプセル化されます。

3. UNIXに導入される前のフォークの登場

1963 年、メルビン・コンウェイは、複数のプロセッサ上でプロセスを並列に実行する手段としてフォークのアイデアを提案しました。

1969 年の Thompson バージョンの UNIX には、オーバーレイ テクノロジを使用してコマンドを実行する 2 つのシェル プロセスしかありませんでした。

これまでに見たものは次のとおりです。

Thompson バージョンの UNIX には fork、exec、wait がなく、唯一のライブラリ関数のような exit は、現在の exit システム コールとは大きく異なります。明らかに、Thompson バージョンの UNIX はマルチプロセス システムではなく、実行可能な単純な 2 端末のタイムシェアリング システムです。

1. UNIXフォークの誕生

UNIX にフォークはどうやって導入されたのでしょうか?

これは、オーバーレイ テクノロジを使用する Thompson バージョンの UNIX に固有の問題から始まる必要があります。元の論文を見てみましょう。

これらの問題を解決するために、トンプソンは非常にシンプルな解決策を考え出しました。

  • シェル プロセスを破棄せずに常駐させます。コマンドが実行されると、ディスクにスワップされます。

当然ですが、コマンド プログラムはシェル プロセスを上書きすることはできません。解決策は、「スワッピング」と呼ばれる技術を使用することです。

スワッピングとオーバーレイの両技術は、実際には、限られたメモリをマルチプロセスで使用するという問題に対するソリューションです。違いは方向にあります。

  • オーバーレイ テクノロジーとは、現在のプロセス メモリ イメージを別のプロセス ディスク イメージで上書きすることを指します。
  • スワッピング技術とは、プロセスのメモリ イメージをディスクにスワップし、別のプロセスのディスク イメージをロードすることを指します。

スワッピングを使用して上書きの問題を解決するには、新しいプロセスを作成する必要があります。

  • コマンド プログラムを新しいプロセスで実行します。

UNIX を変更する必要があり、2 つのクォータ プロセス テーブルでは明らかに不十分です。もちろん、解決は難しくありません。

効率性に関しては、コピーは創造性よりも劣ります。新しいプロセスを作成する最も直接的な方法は、現在のシェル プロセスをコピーし、コピーした新しいプロセスでそれを上書きすることです。コマンド プログラムはコピーした新しいプロセスを上書きし、現在のターミナル シェル プロセスはそのまま維持するためにディスクにスワップされます。

オーバーレイとスワップを組み合わせることで、UNIX は近代化に一歩近づきます。

現在のプロセスをコピーするソリューションを決定した後、次の質問はプロセスをどのようにコピーするかです。

さて、フォークに戻りましょう。

Conway がフォークのアイデアを提案した後、フォーク実装のプロトタイプがすぐに利用可能になりました (Conway 自身が言ったように、彼は存在する可能性のあるアイデアを提案しただけで、実装はしませんでした)。Project Genie は、フォークを実装するためのより完全なシステムの 1 つと考えられています。

Project Genie システムのフォークは、プロセスを盲目的にコピーするだけではなく、割り当てるメモリ領域の量、コピーする必要なリソースなど、フォーク プロセスを細かく制御します。明らかに、Project Genie のフォークは Conway のマルチプロセッサ並列ロジックを対象としています。

古い諺にあるように、コピーは作成よりも悪いです。UNIX でプロセスのコピーを実装する場合、Project Genie という既製のテンプレートがあります。ただし、Project Genie のフォークは UNIX には複雑すぎ、高度すぎます。明らかに、UNIX にはそのような高度な制御は必要ありません。UNIX は、複数のプロセッサで並列ロジックを実行させるのではなく、フォークされた新しいプロセスを上書きすることだけを望んでいます。

言い換えれば、UNIX は単に fork のコピー ロジックの実装を借用して、別のことを実現しただけです。

つまり、UNIX は fork を非常に大雑把に実装したのです。つまり、親プロセスを完全にコピーします。これは、現在でも使用されている fork システム コールです。

近道をする:

  • フォークは新しいプロセスを上書きするためのものではありません。そうでなければ、なぜそうするのでしょうか? Fork を使用すると、プログラム フローを分割して並列処理を行うことができます。

UNIXフォークが誕生しました!

UNIX フォークが誕生する前の状況を振り返ってみましょう。

フォーク誕生後のシーンを見てみましょう。

こうして、UNIX は正式に近代化の旅を開始し、今日まで続いています。

2. UNIX フォーク実行

exec については特に言うことはありません。これは実際には前述の上書きロジックをカプセル化したものです。その後、プログラマーは上書きロジックを自分で記述する必要はなく、exec システム コールを直接呼び出すことができます。

こうして、古典的な UNIX の fork-exec シーケンスが形成されました。

3. UNIX フォーク/実行/終了/待機

UNIX に fork が導入された後、exit のセマンティクスが劇的に変化したことは注目に値します。

1969 年のオリジナルの Thompson バージョンの UNIX では、端末ごとにプロセスが 1 つしかなかったため、上書きは常にシェル プログラムと何らかのコマンド プログラムの間で行われていました。

  • シェルはコマンド A を実行します。コマンド プログラム A はメモリ内のシェル コードを上書きします。
  • コマンド A が実行されます。シェルは完了したコマンド A のメモリ コードを上書きします。

しかし、フォークが導入された後、シェルはコマンドを実行するときに、フォークされたシェルの子プロセスを特定のコマンド プログラムで上書きしましたが、コマンドが実行されると、シェルが終了していないため、終了ロジックはシェルが現在のコマンド プログラムを上書きすることを許可できなくなりました。親プロセスとしてディスクにスワップされるだけでした (後に、メモリが複数のプロセスに対応できるほど大きくなると、スワップも不要になりました)。

では、現在のプロセスを上書きするために誰が exit let を実行するのでしょうか?

答えは、上書きする必要がないということです。exit の文字通りの意味によれば、単に終了する必要があります。

独自のリソースを管理するという原則に沿って、exit では割り当てられたリソースをクリーンアップするだけで済みます。たとえば、独自のメモリ空間やその他のデータ構造をクリーンアップします。

子プロセス自体については、親プロセスによって生成されるため、親プロセスによって管理および解放されます。このようにして、古典的な UNIX プロセス管理の 4 つの要素セットが正式に形成されました。

Unix/Linux フォークの隠れたオーバーヘッドに関するこの記事はこれで終わりです。Unix/Linux フォークの詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。今後とも123WORDPRESS.COMをよろしくお願いいたします!

以下もご興味があるかもしれません:
  • Linux インデックスノード inode の詳細な説明
  • Linux デバイスに空き容量がありません inode の満杯により 500 エラーが発生します
  • Linux ネットワーク設定の詳細
  • MyCat を使用して Linux で MySQL マスター/スレーブの読み取り/書き込み分離を実装する方法
  • Linux での UDP について学ぶ
  • Linux スワップ パーティション (詳細説明)
  • Linux での C++ ネットワーク プログラミング、epoll テクノロジ、Windows での IOCP モデル
  • Linux サーバーは最大いくつのポートを開くことができますか?
  • Linux ファイル記述子、ファイルポインタ、および inode の詳細

<<:  JavaScript の組み込みオブジェクト 数学と文字列の詳細な説明

>>:  HTML マルチヘッダーテーブルコード

推薦する

Win7 での mysql5.5 インストール グラフィック チュートリアル

MySQL のインストールは比較的簡単なので、通常は次のステップに直接進み、注意が必要な点に集中する...

15行のCSSコードがAppleデバイスをクラッシュさせる可能性があり、最新のiOS 12も例外ではない

たった15行のCSSでiPhoneがクラッシュするWire のセキュリティ研究者 Sabri Had...

HTML で入力ボックスに純粋な数字のみを入力するように制限する方法

inputボックスを純粋な数字のみに制限する1、onkeyup = "value=valu...

MySQL 8.0.16 winx64 のインストールと設定方法のグラフィックチュートリアル

最近、データベースについて学び始めました。最初にやったことは、データベースとは何か、データベースとデ...

優れたウェブフロントエンドデザインの指標

Web ページのアクセシビリティは、フロントエンドでのみ評価および実装できるもののようです。ユーザビ...

docker compose を使ってワンクリックで分散構成センター Apollo を展開するプロセスの詳細な説明

導入分散について話すときは、分散構成センター、分散ログ、分散リンク トラッキングなどについて考える必...

コードレイン効果を実現するJavaScriptキャンバス

この記事では、コードレイン効果を実現するためのキャンバスの具体的なコードを参考までに共有します。具体...

Apache ab を使用して HTTP パフォーマンス テストを実行する

MacにはApache環境が付属していますターミナルを開き、sudo apachectl -v と入...

Facebook 出会い系サイトデザインのユーザー エクスペリエンス分析

<br />関連記事: Facebookの情報アーキテクチャの分析 元記事: http:...

ウェブサイトのコードブロックのpreタグにコピーコードボタンコードを追加します

他のよりプロフェッショナルなブログ システムを参照すると、コード ブロックにコードのコピー ボタンが...

Centos7 システム上の nginx サーバーで Phalcon 環境を構築する方法の詳細な説明

この記事では、centos7 システムの nginx サーバーの下に phalcon 環境を構築する...

サーバー上で selenium+chromedriver を実行するための詳細なチュートリアル

1. はじめにSelenium を使用して Web サイトからデータをスクレイピングしたいのですが、...

Vueでスワイパープラグインを使用する際の問題を解決する

デモを作成するときにこのプラグインを使用していくつか問題が発生したため、プラグインの使用方法といくつ...

Vue3はフロントエンドのログを出力するためにaxiosインターセプターを使用する

目次1. はじめに2. axiosインターセプターを使用してフロントエンドログを出力する1. はじめ...

Vue パッケージサイズの最適化の実装 (1.72M から 94K)

1. 背景最近、独立した開発者がUIデザインを行うのを支援するために、uideaというWebサイト...