私は学び、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を消費する必要があるプロセスに適しています))または〜のため特権の分離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)
sshdはroot
クライアント接続(28571)から独自のコピーをフォークし、権限の分離のために別のコピー(14625)をフォークします。
答え2
たくさんあります。
fork()
呼び出さないプログラムはexec()
通常、子プロセスを生成するパターンに従います。作業プロセスメインプロセスとは異なるプロセスでさまざまなタスクを実行するために使用されます。dhclient
、、、などphp-fpm
のさまざまなプログラムでこれを見つけることができますurxvtd
。
exec()
呼び出さないプログラムfork()
はチェーンローディング、他のプログラムイメージでプロセスを上書きします。処理状態に対して特定のタスクを実行し、変更されたプロセス状態で実行するために他のプログラムを実行するチェーンローディングユーティリティの完全なサブカルチャーがあります。これらのユーティリティは、一般的に以下にあります。デーモンツールシリーズサービスおよびシステム管理ツールセット(これに限定されない)いくつかの例を次に示します。
chpst
ゲリットペプから走るs6-softlimit
そしてs6-envdir
ローラン・ベルコテからs6local-reaper
そしてmove-to-control-group
私からスナックツールセットrdprio
idprio
FreeBSDからnumactl
FreeBSDとLinuxで
daemontoolsツールセットシリーズには以下が含まれます。たくさんこれらのツールは以下で提供されます。machineenv
渡すfind-matching-jvm
到着runtool
。
答え3
他の答えに加えて、デバッガはしばしばptrace
来る。デバッグオブジェクトは、親プロセス(デバッガ)によって追跡されていることを示すために独自に表示するために使用する必要があります。これは、デバッガに必要な権限を付与するためのものです。fork
exec
PTRACE_TRACEME
したがって、デバッガが最初にフォークされます。子供がptrace
最初に電話をPTRACE_TRACEME
してから電話をかけますexec
。これで、子実行者のプログラムを親実行者が追跡できるようになりました。
答え4
フォークなしで実行
このようなタスクを実行するには、少なくとも2つの理由があります。
- チェーンローディング。現在のプロセスイメージは他のイメージに置き換えられます。
- 現在実行中のプログラムを再起動します。たとえば、SIGHUPまたはサーバープロセスの両方を再ロードしてクリーンブートを実行すると、これが発生する可能性があります。ある程度は、これがチェーンローディングであり、同じプログラムとの偶然の一致であると考えることもできます。
execのないフォーク
これは、各デーモンが起動するたびに(実際には2回)実行されます。これは、シェルが停止せず(シェルが終了するのを待っていた元のプロセスが終了するため)、デーモンがターミナル制御下になくなったため、シェルウィンドウを閉じてもデーモンが終了しないなど、さまざまなことを行います。
もう1つの一般的な用途は、約25年前にApache Webサーバーで有名になったワーカーの子をフォークすることです(現在は、雷雨の問題に対する脆弱性のため、最先端の技術とは見なされませんが、以下を提供します)。可能な限りシンプルで最も強力なサーバーです)。
もう1つの一般的な用途は、一貫したスナップショットを作成することです。fork
プロセスを作成するだけでなく、アドレス空間もコピーします(理論的には、実際にはページ書き込み時のコピーのみを表示します)。これにより、親プログラムがこれ以上変更できなくなったプログラムデータ全体のスナップショットが作成されます。
一部のプログラムはこれを利用します。たとえば、redisはデータをディスクに(一貫した状態で)保存しますが、改訂するデータセットは同時に実行されます。これは、fork
一貫したスナップショットが作成され、親プロセスの変更が表示されないために機能します。