execve プロセスからそれを開始したプロセスに終了ステータス 0 を送信したい。成功すると execve が返されないため、その後は何もできません。しかし、execveが成功した場合は欲しいです。
2 に答える
以下を使用して、execが成功したことを確認できますFD_CLOEXEC
。
パイプを作成します。
フォーク。
子では、パイプの読み取り側を閉じ、パイプ
FD_CLOEXEC
の書き込み側にフラグを設定します。次に、 に進みますexec
。が成功した場合exec
、パイプは により自動的に閉じられFD_CLOEXEC
ます。失敗した場合exec
は、パイプにバイトを書き込んで終了します。親で、パイプの書き込み側を閉じ、読み取り側から読み取ります。0 バイト (EOF) を読み取った場合は、
exec
成功したことを意味します。パイプでバイトを読み取った場合、それはexec
失敗したことを意味します。
errno
障害が発生した場合にパイプ経由で書き込まれたデータは、 afterの値などのエラー情報を送信するために使用できますexec
。
簡潔にするためにエラー チェックを省略したコードは、次のようになります。
int pipe_fds[2];
pipe(pipe_fds);
if (!fork()) {
close(pipe_fds[0]);
fcntl(pipe_fds[1], F_SETFD, F_CLOEXEC);
execve(...);
write(pipe_fds[1], "", 1);
_exit(1);
}
else {
int n;
char out;
close(pipe_fds[1]);
n = read(pipe_fds[0], &out, 1);
if (n == 0)
printf("exec successful\n");
else
printf("exec failed\n");
close(pipe_fds[0]);
}
他のスレッドが独自のプロセスを並行して実行する可能性がある場合、この手法は安全ではない可能性があることに注意してください。問題は、パイプが作成されてから close-on-exec フラグが設定されるまでに遅延があることです。関係のないスレッドがその重要なウィンドウで fork して exec した場合、子はそれを継承pipe_fds[1]
し、それを閉じないため、親がハングします。pipe2
これは、close-on-exec フラグが設定されたパイプをアトミックに作成できるLinux 固有の呼び出しを使用して修正できます。
終了までにプロセスが開始されるのを待つにはfork()
、次を使用できますwait()
。
/* parent */
int status;
while (wait(&status) != uproc.pid) {
printf("waiting for child to exit");
}
そして、この質問に基づいて
子の終了ステータスは、変数wait
で関数によって提供されます。status
マクロを使用して終了ステータスを取得しますがWEXITSTATUS
、プログラムが正常に終了した (つまり、関数exit
から呼び出された、または返された) 場合のみです。main
if (WIFEXITED(status))
printf("Child exit status: %d\n", WEXITSTATUS(status));
else
printf("Child exited abnormally\n");