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


9

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


2
従来のフォークボム:while(1)fork(); システムリソースを占有します。
ジョシュア

回答:


22

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

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

これの実際の例は次のとおりですGIT_SSH(ただし、上記のラッパープログラムメソッドを実行したくない場合にgit(1)も提供されGIT_SSH_COMMANDます)。

フォークのみは、通常のワーカープロセス(たとえばhttpd、フォークモードのApache)を生成するときに使用されます(ただし、フォークのみは、CPUを消費する必要があるプロセスに適しています。 )またはOpenBSD上の他のプログラムで使用される特権分離sshd(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)

rootsshdがクライアント上で特権分離のために自身のコピー(28571)をフォークし、その後、別のコピー(14625)を接続しています。


14

たくさんあります。

fork()なしで呼び出すプログラムexec()は、通常、メインワーカープロセスとは別のプロセスでさまざまなタスクを実行する子ワーカープロセスを生成するパターンに従います。あなたは、など様々なプログラムでこれを見つけることができますdhclientphp-fpmurxvtd

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

daemontoolsファミリのツールセットにはそのようなツールが多数含まれmachineenvfind-matching-jvmruntoolます。


2

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

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


forkとexecの間で行うことの例はたくさんありますが、最も一般的なのはI / Oのリダイレクト(パイプの設定など)です。しかし、問題は、execなしでforkを実行することです。
Barmar

0

フォークなしのexec

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

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

execなしのフォーク

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

もう1つの一般的な使用法は、25年ほど前にapache Webサーバーで有名になったforking worker childrenです(最近では、雷鳴の群れの問題が発生しやすいため、これは最新技術とは見なされていませんが、可能な限り最もシンプルで最も堅牢なサーバーです)。

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


今日ではほとんどデーモンはありませんが、ほとんどが標準としてこれを行っていないか、一般的に使用されているモードではそうしていません。これは、準備の不一致恐怖につながるフォークの間違いであり、デーモン化の誤りの誤りの1つです。この過ちはついに広く支持されなくなった。
JdeBP '19年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.