1

私はこのような構造を持つプログラムを書く必要があります:

親はFIFOを作成し、次にfork()

  • 子1はstdinからメッセージを読み取り、名前付きパイプ(FIFO)に書き込みます。
  • 次に、親プロセスでパイプ(名前なし)と別のパイプを作成する必要がありますfork()
  • 子番号2はFIFOから読み取り、メッセージの長さをカウントし、パイプ(名前なし)を介して親に番号を送信します。

子供が親と通信できる1つのフォークで簡単なプログラムを作成しました。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO "/tmp/my_fifo"

int main()
{
pid_t fork_result;
int pipe_fd;
int res;
char writer[3];
char reader[3];

res = mkfifo(FIFO,0777);
if (res == 0)
{
    printf("FIFO created!\n");

    fork_result = fork();
    if (fork_result == -1)
    {
        fprintf(stderr, "fork error");
        exit(EXIT_FAILURE);
    }       
    if (fork_result == 0)
    {
        printf("CHILD 1\n");
        pipe_fd = open(FIFO, O_WRONLY | O_NONBLOCK);
        scanf("%s", writer);
        res = write(pipe_fd,writer,3);
        if (res == -1)
        {
            fprintf(stderr,"error writing fifo\n");
            exit(EXIT_FAILURE);
        } 
        (void)close(pipe_fd);
        exit(EXIT_SUCCESS);
    }
    else
    {
        printf("PARENT\n");
        pipe_fd = open(FIFO, O_RDONLY);
        res = read(pipe_fd, reader, 3);
        printf("reader: 0: %c\n",reader[0]);
        printf("reader: 1: %c\n",reader[1]);
        printf("reader: 2: %c\n",reader[2]);
        (void)close(res);
    }         
}
else
{
    printf("deleting fifo... run program again!\n");
    unlink(FIFO);
}
exit(EXIT_SUCCESS);
}

そしてそれは非常にうまく機能しています。そこで、上記のアーキテクチャを持つコードを作成しました。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FIFO "/tmp/my_fifo"

int main()
{
pid_t fork_result;
pid_t fork_result2;
int pipe_fd;
int res;
char writer[3];
char reader[3];

res = mkfifo(FIFO,0777);
if (res == 0)
{
    printf("FIFO created!\n");
    fork_result = fork();

    if (fork_result == -1)
    {
        fprintf(stderr, "fork error");
        exit(EXIT_FAILURE);
    }     

    if (fork_result == 0)
    {
        printf("CHILD 1\n");
        pipe_fd = open(FIFO, O_WRONLY | O_NONBLOCK);
        scanf("%s", writer);
        res = write(pipe_fd,writer,3);
        if (res == -1)
        {
            fprintf(stderr,"error writing to fifo\n");
            exit(EXIT_FAILURE);
        } 
        (void)close(pipe_fd);
    exit(EXIT_SUCCESS);
    }
    else
    {
        printf("PARENt 1\n");
        //don't forget pipe!

        fork_result = fork();
        pipe_fd = open(FIFO, O_RDONLY);
        if (fork_result == 0)
        {
           printf("CHILD 2\n");
           res = read(pipe_fd, reader, 3);
           printf("Odczytano: 0: %c\n",reader[0]);
           printf("Odczytano: 1: %c\n",reader[1]);
           printf("Odczytano: 2: %c\n",reader[2]);
           (void)close(res);
        } 
    }         
}
else
{
    printf("deleting fifo\n");
    unlink(FIFO);
}
exit(EXIT_SUCCESS);
} 

実行シーケンスは次のようになります。

PARENT 1
CHILD 1
CHILD 2

したがって、親1ではFIFOを開いて読み取り、子1ではFIFOに書き込み、子2はそれを読み取る必要があります。私がそれを実行するとき、私はFIFOに何も書くことさえできないので、私はコードで意味します。scanf("%s", writer);最初のプログラムで働いたブロックで。

open()正しく使用していますか?getpid()どこかで使う必要がありますか?fifoに書き込もうとするとブロックされるのはなぜですか。

4

2 に答える 2

1

問題は、CHILD1がでFIFOを開いていることです。これは、他のプロセスが読み取り用にFIFOを開いていない場合、O_NONBLOCK失敗します(EWOULDBLOCKまたはで)。EAGAIN最初のプログラムでは、親はフォークの後で実行を継続し、子が移動する前に読み取り用にFIFOを開いて書き込み終了を開くため、機能します。ただし、2番目のケースでは、親が最初に追加のフォークを実行します。これにより、PARENTまたはCHILD2が読み取り用にFIFOを開く前に、CHILD1がopenコマンドに到達するのに十分な速度で速度が低下するため、CHILD1のオープンは失敗します。

を取り除くと、O_NONBLOCK問題なく動作します(ただし、親と子の両方で読み取るためにFIFOを開くと、おそらく必要なものではありません)。

キーボードから読みたい場合は、別の問題があります。これをシェルから実行すると、PARENTはすぐに(多​​かれ少なかれ)終了するため、シェルはキーボードからのコマンドの読み取りに戻ります。これは、CHILD1とシェルが入力をめぐって争うことを意味します。一方、最初に説明したことを実行し、PARENTにCHILD2からのパイプからの読み取りを待機させる場合は、必要な処理を実行する必要があります。

于 2013-02-01T18:03:27.197 に答える
0

同じ変数fork_resultを2回使用しているからではありませんか?使用しない別の変数fork_result2を作成したため、おそらく意図しないものです。

これで問題が解決するかどうかはわかりませんが、少なくとも2番目のフォークでfork_result2を使用すると、理解しやすくなります...

于 2013-02-01T18:03:07.730 に答える