親プロセスは常に子プロセスの後に出力を印刷します。

親プロセスは常に子プロセスの後に出力を印刷します。

Solaris 11.3 で実行される次のコードを検討してください。

int main(void) {
    pid_t pid = fork();
    if (pid > 0) {
        printf("[%ld]: Writing from parent process\n", getpid());
    }
    if (pid == 0) {
        execl("/usr/bin/cat", "/usr/bin/cat", "file.c", (char *) 0);
        perror("exec failed");
        exit(1);
    }
 }

実行するたびに、「write from parent」行が常に最後に出力されます。私の学校の課題で子プロセスが完了した後にのみ行を印刷するためにwait(2)を使用しなかった場合、この結果は驚くことはありません。なぜこれが起こり、この問題を解決するためにwait(2)またはwaitpid(2)を安全に使用できるように、子プロセスがcatを実行する前に(または順序が少なくとも定義されていない場合)、この行が印刷されるようにします。するにはどうすればよいですか?

ベストアンサー1

@AndrewHenleが述べたように、特定の順序でプロセスをスケジュールするためにシステムに頼ることは安全ではなく不合理です。あなたの場合のようにスケジュールが一貫しているように見えても、オペレーティングシステムの実装者がスケジューラの動作を変更するのを防ぐ方法はありません。

プロセス/スレッド間の作業順序が関係する場合は、ある種の通信が必要です。

あなたのシナリオでは、簡単なブロッキング読み取りがアクションを実行します。フォークの前にパイプを作成します。その後、親はメッセージを印刷した後にのみ親のパイプに書き込みます。同時に、パイプからデータを読み取ろうとする子プロセスは、親プロセスが書き込むまで実行をブロックします。

各プロセスでエラー処理と廃止されたパイプファイル記述子(通常は分岐後に明示的に閉じる)を無視します。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/wait.h>

int main(void) {

    char buf[1];
    int pipe_fds[2];
    pipe(pipe_fds);

    pid_t pid = fork();
    if (pid > 0) {
        printf("[%ld]: Writing from parent process\n", getpid());
        write(pipe_fds[1], "_", 1);
        wait(NULL);
    }
    if (pid == 0) {
        read (pipe_fds[0], buf, 1);
        execl("/usr/bin/cat", "/usr/bin/cat", "file.c", (char *) 0);
        perror("exec failed");
        exit(1);
    }

端末で実行している場合は、子の出力とシェルプロンプトがインターリーブされないように、親で待機を使用する必要があります。

おすすめ記事