3

このコードを考えると:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world! I'm the son and this my message!\n";
        char    readbuffer[80];

        pipe(fd);   // piping fd[0] & fd[1]

        if((childpid = fork()) == -1)   // here we create a SON process
        {
                perror("fork");
                exit(1);
        }

        if(childpid == 0)    // child process
        {
                /* Child process closes up input side of pipe */
                close(fd[0]);       // closing the READ end from reading , after that the SON would write into fd[1]

                /* Send "string" through the output side of pipe */
                write(fd[1], string, (strlen(string)+1));
                printf("Verification : Message was sent successfully by the SON!\n");
                exit(0);
        }
        else    // father process
        {
                /* Parent process closes up output side of pipe */
                close(fd[1]);

                /* Read in a string from the pipe */
                nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
                printf("I'm the father and I received that string: %s", readbuffer);
        }

        return(0);
}

出力は次のとおりです。

I'm the father and I received that string: Hello, world! I'm the son and this my message!
Verification : Message was sent successfully by the SON!

私はパイプを理解しようとしていますが、はっきりしないことがいくつかあります:

  1. 息子がその行でメッセージを送信しwrite(fd[1], string, (strlen(string)+1));、その後、メッセージが送信されたことを確認するメッセージが表示された場合、父親が息子からメッセージを受信したprintf、なぜ確認(たとえばVerification : Message was sent successfully by the SON! )を取得するのですか?最初に息子からの確認であり、次に文字列であると想定されていませんでしたか?

  2. 父親がパイプから読み込もうとし、息子がパイプに書き込みたい場合、ここのどこかにデッドロックが隠されていますね。なぜデッドロックが発生しないのですか?

ありがとう

4

5 に答える 5

3

あなたの最初の質問:

1. wasn't it suppose to be first the verification from the son and only then the string ?

回答:複数のプロセスを実行している場合、それらのプロセスの命令の実行シーケンスは決定論的ではありません。どのプロセスがいつスケジュールされるかはスケジューラーによって異なります。したがって、プログラムの出力から、命令の実行シーケンスを次のように知ることができます。

CHILD-PROCESS: write(fd [1]、string、(strlen(string)+1)); \\この指示の後、このプロセスは中断されます

PARENT-PROCESS:nbytes = read(fd [0]、readbuffer、sizeof(readbuffer));

PARENT-PROCESS:printf( "私は父親であり、その文字列を受け取りました:%s"、readbuffer);

CHILD-PROCESS: printf( "検証:メッセージはSONによって正常に送信されました!\ n");

このシーケンスは、他の場合と同様に異なる場合があります。

あなたの2番目の質問:

2. Why am I not getting a deadlock ?

回答:この状況では、親プロセスはパイプでの入力の待機をブロックするだけです。しかし、子供は書くことができます、それは待つ必要はありません。したがって、デッドロックの可能性はありません。

于 2012-07-16T12:22:48.810 に答える
2

1)子プロセスからのメッセージが後で来る理由は、パイプへの書き込みがバッファーに十分なスペースができるまで(ここから)ブロックされる可能性があるためです。

プロセスが完全なパイプに書き込もうとすると(以下を参照)、書き込みを完了するのに十分なデータがパイプから読み取られるまで、write(2)がブロックします。

つまり、子プロセスは、への呼び出し内で親プロセスがメッセージを読み取るのを待ちますwrite()

2)子プロセスがパイプへの書き込みに失敗した場合、親はブロックします(デッドロックは発生しません)。

于 2012-07-16T11:46:27.110 に答える
2

I / Oバッファリングのため、出力が印刷された順序で表示される保証はありません。

于 2012-07-16T11:51:15.390 に答える
1
    if(childpid == 0)    // child process
    {
            write(fd[1], string, (strlen(string)+1)); #C1
            printf("Verification : Message was sent successfully by the SON!\n"); #C2
            exit(0);
    }
    else    // father process
    {
            /* Read in a string from the pipe */
            nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); #F1
            printf("I'm the father and I received that string: %s", readbuffer); F2
    }

上記の場合、 C1とF1のどちらが最初に発生するかはわかりません。これはカーネルのスケジューリングに依存するため、信頼すべきではありません。ただし、パイプがボックモードの場合、C1とF1の両方が関連しています。Related =両方が発生する必要があります。そうしないと、デッドロックが発生します。次の状況では、デッドロックが発生します。

  1. 子はC1を実行していませんが、入力を待つなどの何かを実行して戻ってこない場合、親はF1でデッドロックされます。
  2. 親はF1を実行していませんが、入力を待つなどの何かを実行して戻ってこない場合、子はC1でデッドロックされます。

どちらかの子/親が終了すると、壊れたパイプ/シグパイプが表示されます。

于 2012-07-16T12:13:30.330 に答える
1

子がパイプに書き込むと、カーネルは親を実行状態に変更します。write子がテキストを印刷する前に(おそらく子が呼び出しから戻る前に)、スケジューラーが親を実行に切り替えているようです。

だからライン

printf("I'm the father and I received that string: %s", readbuffer);

行の前に実行されます:

printf("Verification : Message was sent successfully by the SON!\n");

コマンドを使用してこれを確認できますstrace -f

于 2012-07-16T11:53:23.413 に答える