1

これがプロデューサーです。

// speak.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define FIFO_NAME "american_maid"

int main(void)
{
    char s[300];
    int num, fd;

    mknod(FIFO_NAME, S_IFIFO | 0666, 0);

    printf("waiting for readers...\n");
    fd = open(FIFO_NAME, O_WRONLY);
    printf("got a reader--type some stuff\n");

    while (gets(s), !feof(stdin)) {
        if ((num = write(fd, s, strlen(s))) == -1)
            perror("write");
        else
            printf("speak: wrote %d bytes\n", num);
    }

    return 0;
}

そしてこれが消費者です。

//tick.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#define FIFO_NAME "american_maid"

int main(void)
{
    char s[300];
    int num, fd;

    mknod(FIFO_NAME, S_IFIFO | 0666, 0);

    printf("waiting for writers...\n");
    fd = open(FIFO_NAME, O_RDONLY);
    printf("got a writer\n");

    do {
        if ((num = read(fd, s, 300)) == -1)
            perror("read");
        else {
            s[num] = '\0';
            printf("tick: read %d bytes: \"%s\"\n", num, s);
        }
    } while (num > 0);

    return 0;
}

それらを実行すると、Producer が出力します。

waiting for readers...

そして、消費者のアウトプット、

waiting for writers...

speakがリーダーを見つけられない、tick . ここでの理論から私が得たように、open() (speak.c) はopen() (tick.c) が開かれるまでブロックされたままになります。そしてその逆。だから、デッドロックか何かが起こっていると思います。これの解決策が必要です。

4

2 に答える 2

0

私の環境では問題なく動作します。リーダーとライターの準備ができていれば、open が返されます。open がブロックされているため、私の意見では mknod 関数は成功です。これら 2 つのプロセスを別のパスで実行している可能性があります。

于 2012-05-14T10:47:56.710 に答える
0

リーダーとライターの間に競合状態があるようです。

これを修正するには、ライターが「アクティブ」になるまでリーダーを起動しない方法が必要です。このために、パイプを作成し、ライターの準備ができたらそれに書き込むことをお勧めします。次に、フォークの読み取り側からの読み取りが成功すると、FIFO が準備され、リーダーが動作するはずです。

ここではフォークを使用する必要があります。親プロセスと子プロセスの間でミューテックスを調整するのは簡単ではなく、パイプを適切に行う方が簡単だからです。

また、あなたはmknod()2回電話しました。確かに、それは -1 を返しますerrno == EEXISTが、もっと注意してください。これを回避するには、リーダーとライターをパスを引数とする関数にします。

ライターをint speak(const char *fifo, int pipefd)に、リーダーを に書き換えますint tick(const char *fifo)

次に、次のようなラッパーを作成します。

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

const char fifo_name[] /* = ... */;

int speak(const char *fifo, int pipefd);
int tick(const char *fifo);

int main() {
    int pipefd[2];
    pipe(pipefd);

    mknod(fifo_name, S_IFIFO | 0666, 0);

    if (fork() == 0) {
        close(pipefd[0]);
        return speak(fifo_name, pipefd[1]);
    } else {
        close(pipefd[1]);
        char foo;
        read(pipefd[0], &foo, 1);
        return tick(fifo_name);
    }
}

fifo が作成された後 (つまり、 への呼び出しの直後)、渡された fd にバイト (何でも) を出力するようにライターを変更しますopen(..., O_WRONLY)

簡潔にするためにエラー チェックを省略したため、コードをそのまま使用しないでください。

于 2012-05-13T08:22:40.073 に答える