6

私はできる必要があります:

  1. プロセスをフォークしてexecvpにします(私はそれをしました)
  2. 子プロセスexecvpが成功したかどうかを確認します(方法がわかりません)
  3. 子プロセスが終了したかどうかを確認します(問題があります)

プロセスをフォークしていますが、子のexecvpが機能したか失敗したかを確認する方法がありません。それが失敗した場合、私はそれが失敗したことを知ることができる必要があります。現在使用しています

-1 != waitpid( pid, &status, WNOHANG )

しかし、pidプロセスのexecvが失敗した場合、waitpidは-1を返さないようです。

どうすれば確認できますか?waitpidのmanページを読みましたが、はっきりしていません。多分私の英語は十分ではありません。

編集:もっと説明するために:
私はホームワークのために自分のターミナルを構築しています。入力としてコマンド文字列を取得する必要があります。たとえば、「ls」と言ってから、コマンドを実行する必要があります。
子がフォークした後、子はコマンドを実行するためにexecvpを呼び出し(文字列を解析した後)、親はコマンドの最後に「&」があるかどうかを確認する必要があります。
コマンドの最後に記号「&」が存在しない場合、親は子が実行されるのを待つ必要があります。

したがって、execvpが失敗したかどうかを知る必要があります。失敗しなかった場合、親はwaitpidを使用して、子が実行を終了するのを待ちます。失敗した場合、親は子を待ちません。

4

2 に答える 2

6

#2の一般的な解決策は、fork()の前にパイプを開き、execの後に子に書き込むことです。親では、読み取りが成功したということは、execが失敗したことを意味します。読み取りが失敗したということは、execが成功し、書き込みが行われなかったことを意味します。

// ignoring all errors except from execvp...
int execpipe[2];
pipe(execpipe);
fcntl(execpipe[1], F_SETFD, fcntl(execpipe[1], F_GETFD) | FD_CLOEXEC);
if(fork() == 0)
{
    close(execpipe[0]);
    execvp(...); // on success, never returns
    write(execpipe[1], &errno, sizeof(errno));
    // doesn't matter what you exit with
    _exit(0);
}
else
{
    close(execpipe[1]);
    int childErrno;
    if(read(execpipe[0], &childErrno, sizeof(childErrno)) == sizeof(childErrno))
    {
        // exec failed, now we have the child's errno value
        // e.g. ENOENT
    }
}

これにより、親はexecが成功したかどうか、および副産物として失敗した場合のerrno値を明確に知ることができます。

WEXITSTATUSexecが成功した場合でも、子プロセスは終了コードで失敗する可能性があり、マクロを使用してステータスを調べると、その状態もわかります。

注:フラグをwaitpid使用した呼び出しWNOHANGは非ブロッキングであり、有効なpidが返されるまでプロセスをポーリングする必要がある場合があります。

于 2012-11-20T21:37:25.090 に答える
4

exec呼び出しは、成功した場合はまったく返されません。これは、現在のプロセスイメージが別のプロセスイメージに置き換えられるためです。したがって、実行された場合は、エラーが発生したことを意味します。

execvp(...);
/* exec failed and you should exit the
   child process here with an error */
exit(errno);

親プロセスに失敗したかどうかを知らせるにexecは、子プロセスのステータスを読み取る必要があります。

waitpid(pid, &status, WNOHANG);

次にWEXITSTATUS(status)、マニュアルページからマクロを使用します。

WEXITSTATUS(status)は、子の終了ステータスを返します。 これは、子がexit(3)または_exit(2)の呼び出しで、またはmain()のreturnステートメントの引数として指定したステータス引数の最下位8ビットで構成されます。

最後のステートメントはexec、コマンドが成功して実行されると、main()そのコマンドの関数の終了ステータスを取得することを意味します。つまり、この方法で失敗したコマンドと失敗したコマンドの違いを確実に区別することはできないexecため、あなたにとって重要です。

別の問題:

コマンドの最後に記号「&」が存在しない場合、親は子が実行されるのを待つ必要があります。

子プロセスをゾンビ状態のままにしないようにするためwait()に、プログラムのある時点で子プロセスを呼び出す必要があります。&

注:これを使用すると、プロセスの状態が変更されていない場合、つまりブロックされない場合にすぐに戻るWNOHANGことを意味します。それ以外の場合は、メインループの一部として使用または呼び出します。waitpid()wait()waitpid()

于 2012-11-20T21:32:37.987 に答える