私はfork()およびexec()コマンドについて学習しています。 fork()とexec()は通常一緒に呼び出されるようです。 (fork()は新しい子プロセスを作成し、exec()は現在のプロセスイメージを新しいプロセスに置き換えます。)ただし、各関数を独自に呼び出すシナリオはどれですか。このようなシナリオはありますか?
承知しました! 「ラッパー」プログラムの一般的なパターンは、さまざまなことを実行してから、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)を分岐しました。
たくさんあります。
fork()
なしでexec()
を呼び出すプログラムは、通常、さまざまなタスクをメインに対して個別のプロセスで実行するために、子プロセスワーカープロセスのパターンに従っています1。これは、dhclient
、_php-fpm
_、urxvtd
などのさまざまなプログラムで見つかります。
exec()
なしでfork()
を呼び出すプログラムはchain loadingで、そのプロセスを別のプログラムイメージでオーバーレイします。特定の処理を行って状態を処理し、別のプログラムを実行してその改訂された処理状態で実行する、チェーン読み込みユーティリティのサブカルチャー全体があります。このようなユーティリティは、サービスおよびシステム管理ツールセットの daemontoolsファミリ で一般的ですが、これらに限定されません。いくつかの例:
chpst
Gerrit Papeの runit からs6-softlimit
_ および _s6-envdir
_ Laurent Bercotの s6 からlocal-reaper
_ および _move-to-control-group
_ my from nosh toolsetrdprio
およびidprio
numactl
FreeBSDおよびLinuxの場合Daemontoolsファミリーのツールセットには machineenv
から _find-matching-jvm
_ までのそのようなツールがたくさんあります。 runtool
へ。
他の回答に加えて、ptrace
を使用するデバッガーは通常、fork
とexec
の間のギャップを利用します。デバッグ対象は、自身がPTRACE_TRACEME
でマークされ、親プロセスであるデバッガによってトレースされていることを示す必要があります。これは、デバッガに必要な権限を与えるためです。
そのため、デバッガは最初に自身をフォークします。子はptrace
をPTRACE_TRACEME
で呼び出してから、exec
を呼び出します。子execのどのプログラムでも、親が追跡できるようになります。
そのようなことをしたいと思う理由は少なくとも2つあります。
これは、すべてのデーモンが起動されるたびに(実際には2回)実行することです。これはいくつかのことを行いますが、シェルはハングせず(シェルが待機する元のプロセスが終了するため)、デーモンはターミナルによって制御されなくなるため、シェルウィンドウを閉じてもデーモンは終了しません。
もう1つの一般的な使用法は、25年ほど前にApache Webサーバーで有名になった、ワーカーの子供をフォークすることです(現在、雷鳴の群れの問題が発生しやすいため、これは最新の技術とは見なされていませんが、最も単純で、最も堅牢なサーバーを可能にします)。
さらに別の一般的な用途は、一貫したスナップショットを作成することです。 fork
は、プロセスを作成するだけでなく、アドレススペースもコピーします(理論的には、ページにコピーオンライトのみをマークします)。これにより、(原子的に)親が変更できない完全なプログラムデータのスナップショットが作成されます。
いくつかのプログラムはそれを利用しています。たとえば、redisはデータを(整合性のある状態で)ディスクに保存し、同時にmodifyingデータセットを同時に保存します。これが機能するのは、fork
が、親プロセスによる変更を認識しない一貫したスナップショットを作成したためです。