6

Linux のマニュアル ページから:

このvfork()関数は と同じ効果がありますが、プロセスが [...]ファミリの関数fork(2)の 1 つを正常に呼び出す前に [...] 他の関数を呼び出した場合の動作は未定義です。exec(3)

exec*()これは、後で任意の関数を呼び出すことvfork()が許容されることを示唆しています。ただし、マニュアルページの後半では、具体的に次のように述べています。

特に、プログラマーは、子 [...] が [...] を呼び出すまで、親がブロックされたままになることに依存できませんexecve(2)

execve(2)は man ページで繰り返し使用されており、その使用法は、 のexec後に受け入れられる唯一のタイプの関数であることを示唆していvfork()ます。

では、なぜ がここで選ばれているのでしょうか。他のタイプの関数 ( など)execveを呼び出しても安全でしょうか?execexeclp

4

3 に答える 3

5

に電話する必要がありますexecve。他の exec-family 関数のいずれかが、 の後に安全でないアクションを実行しないという保証はありませんvfork。例えば:

  • execl引数リストにメモリを割り当てることができます。async-signal-safe である必要があります。つまり、 を使用する可能性は低いですが、使用しない場合でも、基になるものが実行されmallocた後に割り当てられたメモリ (親のメモリ空間に存在する) を解放する方法はありません。execveスタック上に引数リストを作成できない限り、(せいぜい) 親でメモリ リークが発生します。

  • execvpパス検索を実行するために環境にアクセスする必要があり、 に渡す連結パス名を作成する必要もありますexecve。後者は割り当てが必要な場合があり、前者はあらゆる種類の unsafe-after- vforkthings を実行する場合があります (注: execvpasync-signal-safe でさえありません)。

本当に使用しないでくださいvfork。その使用を安全にすることはほとんど不可能です。特に、すべてのシグナルをブロックしない限り、親のメモリを共有している間にシグナルハンドラーが子で実行される可能性があるため、シグナルハンドラーを使用しているプログラムでは安全ではありません (その場合、子は exec の後に完全にブロックされたシグナルマスクを継承します。ほぼ確実にあなたが望むものではありません)。

のより効率的な代替手段を探している場合はfork、 を使用してposix_spawnください。

于 2014-06-14T19:10:34.837 に答える
1

マニュアルをもう一度読むと、次の 2 つの説明があることが明らかになりますvfork

POSIX 標準の説明によると、 の後vforkに関数の 1 つをexec(3)呼び出す必要があります。

Linux の説明には、vfork, execve(2)(およびのみ execve) の後に呼び出す必要があると記載されています。

execPOSIX標準記述が、関数のいずれかを呼び出すことを許可するために準拠する実装を必要とするかどうかは、私には明らかではありません。標準記述の 1 つの考えられる読み方は、どのexec関数が許可されるかを実装が決定する可能性があるということです (そして、少なくとも 1 つの関数が a の後に許可されることのみを必要としますvfork)。

いずれにせよ、Linux ではexecve( execve* のみ) の後にvfork. POSIX 標準では他のexec機能が許可されている場合がありますが、Linux では許可されていません。

*まあ、もちろん、それも呼び出すことができますが、この Q&A では_exit無視します。_exit

于 2014-11-07T22:58:54.007 に答える