2009-05-29 5 views
9

forkシステムコールは、呼び出しプロセスのクローンを作成し、次に(通常)子プロセスが画像を変更して新しいプロセスを実行するためにexecveシステムコールを発行すると言われています。なぜこの二段階ですか?forkとexecveシステムコールについて

ところで、execveは何の略ですか?

答えて

8

各ステップは比較的簡単です。

UNIXでは、アプリケーションコード( "text")を持つ読み取り専用メモリ領域と読み書き可能メモリ領域( "data")の2つの部分があります。

フォークは読み書き領域をクローンし、テキストページだけを残します。これで、同じコードを実行する2つのプロセスが作成されました。それらは、親と子を分けるレジスタ値(forkの戻り値)によって異なります。

execはテキストページを置き換え、データページだけを残します。 execには、どのくらいの環境情報を渡しているかによって、さまざまな形式のexecがあります。バリアントの追加リストについては、http://linux.die.net/man/3/execを参照してください。

+0

本当に、引数がないので、fork()は何もできません。それはもっと簡単にできますか? – 0x6adb015

+6

うん、execは "text"だけでなく、mm全体を置き換えます... /usr/src/linux/fs/exec.cと/usr/src/linux/fs/binfmt_elf.cを参照してください。 – ephemient

+1

通常、forkはデータ領域を複製するが、代わりにCOW(Copy-On-Write)としてマークする。親または子のいずれかがデータを変更しようとすると、そのページが複製され、親と子は別のページになります。 – camh

11
  • のexec:実行新しいプロセス
  • V:使用
  • eは引数の配列:幹部の指定だけでなく、環境

他のバリエーションはたくさんある:

int execl(const char *path, const char *arg, ...); 
int execlp(const char *file, const char *arg, ...); 
int execle(const char *path, const char *arg,..., char * const envp[]); 
int execv(const char *path, char *const argv[]); 
int execvp(const char *file, char *const argv[]); 
  • l:関数のリストarg
  • P:使用する$ PATHは、実行可能ファイルを検索します
3

「幹部」ファミリの関数は、新しいプロセスイメージで(それが呼び出された場所から)現在のプロセスイメージを置き換えるので、呼び出しイメージが置き換えられます新しいプロセスイメージ。たとえば。シェル(/ bin/shまたは/ bin/csh)から 'ls'コマンドを実行する場合、シェルは新しいプロセスにフォークし、lsを実行します。 lsコマンドが終了すると、制御は親プロセス(この例ではシェル)に戻されます。

フォーク機能がない場合、シェルは 'ls'プロセスに置き換えられます。このプロセスでは、lsへのexec呼び出し時にメモリ内のシェルイメージが置き換えられたため、終了時にアクセスできない端末が残されます。

「exec」ファミリのバリエーションは、0x6adb015の回答を参照してください。

14

2段階の理由は柔軟性です。 2つのステップの間で、新しく実行されたプログラムが継承する子プロセスのコンテキストを変更できます。変更することがあり

いくつかのものがあります:

  • ファイルディスクリプタ
  • ユーザー/グループID
  • プロセスグループIDとセッションID
  • 現在のディレクトリ
  • リソース制限
  • スケジューリング優先度と親和性
  • ファイル作成マスク(umaskを)

あなたはフォークとexecを分割しませんでしたし、代わりに、単一の卵のようなシステムコールを持っていた、それはこれらのプロセスのそれぞれの引数を取る必要があります場合は、あなたが望んでいた場合は、それらが子供に異なる設定属性プロセス。たとえば、Windows APIのCreateProcessの引数リストを参照してください。

fork/execを使用すると、新しいプログラムを実行する前に、子プロセスの継承可能なプロセス属性を変更できます。

ファイル記述子の設定は、子供のプロセスコンテキストで変更するより一般的なものの1つです。プログラムの出力をキャプチャする場合は、通常はpipe(2)システムコールを使用して親にパイプを作成し、fork(2)の後に親プロセスの書き込み終了を閉じ、 execve(2)を呼び出す前に、子プロセスで読み込みを終了してください。 (また、dup(2)を使ってパイプの子の終わりをファイル記述子1(stdout)に設定します。これは、単一のシステムコールでは不可能または制限的です。

+0

+1。あなたが「子プロセスで異なる設定をしたい場合は、これらのプロセス属性ごとに引数を取る必要があります。 – Tim

+0

どのような柔軟性があるかを示すために、env変数を変更し、forkとexecを分割することを例にしたコード例がありますか? – Tim

+0

@Tim:一例としてhttp://msdn.microsoft.com/en-us/library/ms682425(v=vs.85).aspxを参照してください。その関数呼び出しの引数リストでは、上記。 – camh

関連する問題