fork()とexec()はいつ別々に呼び出されますか?

fork()とexec()はいつ別々に呼び出されますか?

私は学び、fork()命令しexec()ています。ルックスfork()exec()通常一緒に呼び出されます。 (fork()新しいサブプロセスを作成し、exec()現在のプロセスイメージを新しいプロセスイメージに置き換えます。)しかし、どのような状況で各関数を個別に呼び出すことができますか?そんなシナリオはありますか?

答え1

確かに! 「ラッパー」プログラムの一般的なパターンは、さまざまな操作を実行してからexec呼び出しだけで別のプログラムに置き換えることです(パッキングなし)。

#!/bin/sh
export BLAH_API_KEY=blub
...
exec /the/thus/wrapped/program "$@"

実際の例は次のとおりです(GIT_SSH上記のラッパーアプローチを実行したくない場合はgit(1)提供できます)。GIT_SSH_COMMAND

フォーク専用は、いくつかの一般的なワーカープロセスを生成するために使用されます(たとえば、フォークhttpdモードのApache(フォーク専用は、ネットワークI / Oが発生するのを待つプロセスよりもCPUを消費する必要があるプロセスに適しています))または〜のため特権の分離sshdOpenBSDのプログラムやその他のプログラムで使用される(execなし)

$ doas pkg_add pstree
...
$ pstree | grep sshd
 |-+= 70995 root /usr/sbin/sshd
 | \-+= 28571 root sshd: jhqdoe [priv] (sshd)
 |   \-+- 14625 jhqdoe sshd: jhqdoe@ttyp6 (sshd)

sshdはrootクライアント接続(28571)から独自のコピーをフォークし、権限の分離のために別のコピー(14625)をフォークします。

答え2

たくさんあります。

fork()呼び出さないプログラムはexec()通常、子プロセスを生成するパターンに従います。作業プロセスメインプロセスとは異なるプロセスでさまざまなタスクを実行するために使用されます。dhclient、、、などphp-fpmのさまざまなプログラムでこれを見つけることができますurxvtd

exec()呼び出さないプログラムfork()チェーンローディング、他のプログラムイメージでプロセスを上書きします。処理状態に対して特定のタスクを実行し、変更されたプロセス状態で実行するために他のプログラムを実行するチェーンローディングユーティリティの完全なサブカルチャーがあります。これらのユーティリティは、一般的に以下にあります。デーモンツールシリーズサービスおよびシステム管理ツールセット(これに限定されない)いくつかの例を次に示します。

daemontoolsツールセットシリーズには以下が含まれます。たくさんこれらのツールは以下で提供されます。machineenv渡すfind-matching-jvm到着runtool

答え3

他の答えに加えて、デバッガはしばしばptrace来る。デバッグオブジェクトは、親プロセス(デバッガ)によって追跡されていることを示すために独自に表示するために使用する必要があります。これは、デバッガに必要な権限を付与するためのものです。forkexecPTRACE_TRACEME

したがって、デバッガが最初にフォークされます。子供がptrace最初に電話をPTRACE_TRACEMEしてから電話をかけますexec。これで、子実行者のプログラムを親実行者が追跡できるようになりました。

答え4

フォークなしで実行

このようなタスクを実行するには、少なくとも2つの理由があります。

  1. チェーンローディング。現在のプロセスイメージは他のイメージに置き換えられます。
  2. 現在実行中のプログラムを再起動します。たとえば、SIGHUPまたはサーバープロセスの両方を再ロードしてクリーンブートを実行すると、これが発生する可能性があります。ある程度は、これがチェーンローディングであり、同じプログラムとの偶然の一致であると考えることもできます。

execのないフォーク

これは、各デーモンが起動するたびに(実際には2回)実行されます。これは、シェルが停止せず(シェルが終了するのを待っていた元のプロセスが終了するため)、デーモンがターミナル制御下になくなったため、シェルウィンドウを閉じてもデーモンが終了しないなど、さまざまなことを行います。

もう1つの一般的な用途は、約25年前にApache Webサーバーで有名になったワーカーの子をフォークすることです(現在は、雷雨の問題に対する脆弱性のため、最先端の技術とは見なされませんが、以下を提供します)。可能な限りシンプルで最も強力なサーバーです)。

もう1つの一般的な用途は、一貫したスナップショットを作成することです。forkプロセスを作成するだけでなく、アドレス空間もコピーします(理論的には、実際にはページ書き込み時のコピーのみを表示します)。これにより、親プログラムがこれ以上変更できなくなったプログラムデータ全体のスナップショットが作成されます。
一部のプログラムはこれを利用します。たとえば、redisはデータをディスクに(一貫した状態で)保存しますが、改訂するデータセットは同時に実行されます。これは、fork一貫したスナップショットが作成され、親プロセスの変更が表示されないために機能します。

関連情報