web-dev-qa-db-ja.com

fork()とexec()をいつ呼び出すか?

私はfork()およびexec()コマンドについて学習しています。 fork()とexec()は通常一緒に呼び出されるようです。 (fork()は新しい子プロセスを作成し、exec()は現在のプロセスイメージを新しいプロセスに置き換えます。)ただし、各関数を独自に呼び出すシナリオはどれですか。このようなシナリオはありますか?

9
quil

承知しました! 「ラッパー」プログラムの一般的なパターンは、さまざまなことを実行してから、exec呼び出しのみで他のプログラムに置き換える(フォークなし)ことです。

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

この実際の例は_GIT_SSH_です(ただし、上記のラッパープログラムメソッドを実行しない場合は、git(1)は_GIT_SSH_COMMAND_も提供します)。

フォークのみは、通常のワーカープロセス(たとえば、フォークモードのApache httpd)を生成するときに使用されます(ただし、フォークのみは、CPUを消費する必要があるプロセスに適していますが、ネットワークを待機している親指をいじるプロセスには適していません。 I/Oが発生する))または 特権の分離sshdおよびOpenBSDの他のプログラムで使用(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)
_

root sshdは、クライアント接続で、それ自体のコピー(28571)と、権限分離のための別のコピー(14625)を分岐しました。

22
thrig

たくさんあります。

fork()なしでexec()を呼び出すプログラムは、通常、さまざまなタスクをメインに対して個別のプロセスで実行するために、子プロセスワーカープロセスのパターンに従っています1。これは、dhclient、_php-fpm_、urxvtdなどのさまざまなプログラムで見つかります。

exec()なしでfork()を呼び出すプログラムはchain loadingで、そのプロセスを別のプログラムイメージでオーバーレイします。特定の処理を行って状態を処理し、別のプログラムを実行してその改訂された処理状態で実行する、チェーン読み込みユーティリティのサブカルチャー全体があります。このようなユーティリティは、サービスおよびシステム管理ツールセットの daemontoolsファミリ で一般的ですが、これらに限定されません。いくつかの例:

Daemontoolsファミリーのツールセットには machineenv から _find-matching-jvm_ までのそのようなツールがたくさんありますruntool へ。

14
JdeBP

他の回答に加えて、ptraceを使用するデバッガーは通常、forkexecの間のギャップを利用します。デバッグ対象は、自身がPTRACE_TRACEMEでマークされ、親プロセスであるデバッガによってトレースされていることを示す必要があります。これは、デバッガに必要な権限を与えるためです。

そのため、デバッガは最初に自身をフォークします。子はptracePTRACE_TRACEMEで呼び出してから、execを呼び出します。子execのどのプログラムでも、親が追跡できるようになります。

2
bytefire

フォークなしのexec

そのようなことをしたいと思う理由は少なくとも2つあります。

  1. チェーンローディング。現在のプロセスイメージは別のものに置き換えられます。
  2. 現在実行中のプログラムを再起動します(たとえば、SIGHUPまたはそのようなサーバープロセスを実行し、すべてをリロードして完全に新たに開始した場合)。ある意味では、これはチェーンロードであると主張することができ、偶然にも同じプログラムでのみ発生します。

execなしのフォーク

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

もう1つの一般的な使用法は、25年ほど前にApache Webサーバーで有名になった、ワーカーの子供をフォークすることです(現在、雷鳴の群れの問題が発生しやすいため、これは最新の技術とは見なされていませんが、最も単純で、最も堅牢なサーバーを可能にします)。

さらに別の一般的な用途は、一貫したスナップショットを作成することです。 forkは、プロセスを作成するだけでなく、アドレススペースもコピーします(理論的には、ページにコピーオンライトのみをマークします)。これにより、(原子的に)親が変更できない完全なプログラムデータのスナップショットが作成されます。
いくつかのプログラムはそれを利用しています。たとえば、redisはデータを(整合性のある状態で)ディスクに保存し、同時にmodifyingデータセットを同時に保存します。これが機能するのは、forkが、親プロセスによる変更を認識しない一貫したスナップショットを作成したためです。

0
Damon