1

フォークする簡単なプログラムを作成したいと思います。子は名前付きパイプに書き込み、親は名前付きパイプから読み取りと表示を行います。問題は、それが親に入り、最初のprintfを実行した後、それが奇妙になり、他に何もせず、2番目のprintfに到達せず、コンソールに入力する方法にすぎないことです。

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
char t[100];
mkfifo("myfifo",777);
pid_t pid;
pid = fork();
if (pid==0)
{
    //execl("fifo2","fifo2",(char*)0);
    char r[100];
    printf("scrie2->");
    scanf("%s",r);

    int fp;
    fp = open("myfifo",O_WRONLY);
    write(fp,r,99);
    close(fp);
    printf("exit kid \n");
    exit(0);
} else
{
    wait(0);
    printf("entered parent \n"); // <- this it prints
    // whats below this line apparently its not being executed
    int fz; printf("1"); 
    fz = open("myfifo",O_RDONLY); printf("2");
    printf("fd: %d",fz);
    char p[100];
    int size;
    printf("------");
    //struct stat *info;
    //stat("myfifo",info); printf("%d",(*info).st_size);
    read(fz,p,99);
    close(fz);
    printf("%s",p);

    printf("exit"); exit(0);
}
}
4

2 に答える 2

5

mkfifo()関数呼び出しの戻り値のエラー、特にとをチェックする必要がありopen()ます。

への呼び出しによりwait()、現在の場所で問題が発生します。通常、読み取り用に FIFO を開くと、他のプロセスが同じ FIFO を書き込み用に開くまでブロックされます。逆の場合も同様です1。親は子が終了するのを待っており、子は読み取りプロセス、つまり親が FIFO に接続するのを待っています。

1 - FIFOopen()での使用については、以下の注を参照してください。O_NONBLOCK

wait()親プロセスが終了する直前に呼び出しを移動し、への呼び出しでモードを変更すると、差し迫った問題のいくつかが解決されるようですmkfifo()0666

FIFO の使用が終了したら、FIFO を削除することもお勧めします。

unlink("myfifo");

open()IEEE Std 1003.1-2004の関数ドキュメントから:

O_RDONLY または O_WRONLY が設定された FIFO を開く場合:

  • O_NONBLOCK が設定されている場合、読み取り専用の open() は遅延なく返されます。現在読み取り用にファイルを開いているプロセスがない場合、書き込み専用の open() はエラーを返します。

  • O_NONBLOCK がクリアされている場合、読み取り専用の open() は、スレッドがファイルを書き込み用に開くまで、呼び出しスレッドをブロックします。書き込み専用の open() は、スレッドが読み取り用にファイルを開くまで、呼び出しスレッドをブロックします。


次の例は、元の質問のコードと Beej's Guide to Unix IPC の FIFO ページの組み合わせです。

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

#define FIFO_NAME "myfifo"

int main(void)
{
    char buf[256];
    int num, fd;
    pid_t pid;

    if (mkfifo(FIFO_NAME, 0666) < 0)
        perror("mkfifo");

    pid = fork();
    if (pid == 0)
    {
        printf("child - waiting for readers...\n");
        if ((fd = open(FIFO_NAME, O_WRONLY)) < 0)
            perror("child - open");
        
        printf("child - got a reader -- type some stuff\n");
        while (fgets(buf, sizeof(buf), stdin), !feof(stdin))
        {
            if ((num = write(fd, buf, strlen(buf))) < 0)
                perror("child - write");
            else
                printf("child - wrote %d bytes\n", num);
        }

        close(fd);
        exit(0);
    }
    else
    {
        printf("parent - waiting for writers...\n");
        if ((fd = open(FIFO_NAME, O_RDONLY)) < 0)
            perror("parent - open");
        
        printf("parent - got a writer\n");
        do
        {
            if ((num = read(fd, buf, sizeof(buf))) < 0)
                perror("parent - read");
            else
            {
                buf[num] = '\0';
                printf("parent - read %d bytes: \"%s\"\n", num, buf);
            }
        } while (num > 0);

        close(fd);
        wait(0);
    }

    unlink(FIFO_NAME);
    return 0;
}

この例は Linux でテストされています。Ctrl-を押しDてプログラムを終了します。

于 2010-05-29T15:59:15.983 に答える
3

まず、(stdout への) printf の代わりに fprintf を stderr で試してください。

stderr はバッファリングされません。

次に、実際に印刷されるものと印刷されないものを区別できます。

または、少なくともfflush何かを待つ前に追加します。

于 2010-05-29T15:11:40.313 に答える