7

私はCでアプリケーションを開発しています。親と子のプロセスはパイプを介して通信します。パイプに書き込む前に、親プロセスは別のステートメントを実行します。サンプルコードでは、sleep(10)を使用して遅延を作成しました。子プロセスでは、パイプからデータを読み取る必要があります。ただし、子プロセスのパイプの読み取り側ではデータは読み取られません。

int main()
{
    int pid;
    FILE *fp;
    fp = fopen("test.txt","w");
    char *buff;
    int fd[2];
    int count = 0 ;
    pipe(fd);
    pid = fork();
    if(pid == 0)
    {
        close(fd[1]);
        ioctl(fd[0], FIONREAD, &count);
        fprintf(fp,"Value of count: %d ",count);
        buff = malloc(count);
        fprintf(fp,"\n TIME before read: %s",__TIME__);
        read(fd[0], buff, count);
        fprintf(fp,"\nbuffer: %s\n TIME after read %s", buff, __TIME__);
    }
    else{
        close(fd[0]);
        sleep(10);    //delay caused by application specific code replaced with sleep
        write(fd[1],"THIS is it",10);
    }
    fclose(fp);
    return 0;
}

子プロセスをもう一方の端にデータが書き込まれるまで待機させるにはどうすればよいですか?

4

3 に答える 3

6

パイプはブロッキングモードで開かれ、それを変更するために何もしません。これはおそらく意図したことです。

ただし、最初に行うことはパイプで待機しているデータのサイズを要求することなので、その数のバイトの読み取りに盲目的にジャンプします(親がまだ何も書き込んでいないため、コードの実行時にはおそらくゼロになります) )あなたはブロックせず、代わりにあなたが何も要求しなかったのでただ去ります。

これを行うには、選択ループなど、いくつかの方法があります。データが利用可能になるまで読み取りをブロックしたい場合は、1バイトでブロックし、後で残りのデータを入力します。

これは、これを正しく行う方法の例ではありませんが、1バイトを待機し、残りのデータを取得するためにパイプの読み取りサイズを要求し、それを読み取る方法の短いサンプルです。パイプにデータが残りなくなり、親がそれらの端をシャットダウンするまで、これを続けます。

お役に立てば幸いです。

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

int main()
{
    int pid = 0;

    // create pipe pair
    int fd[2];
    pipe(fd);

    pid = fork();
    if (pid == 0)
    {
        // child side
        char *buff = NULL;
        char byte = 0;
        int count = 0;

        // close write side. don't need it.
        close(fd[1]);

        // read at least one byte from the pipe.
        while (read(fd[0], &byte, 1) == 1)
        {
            if (ioctl(fd[0], FIONREAD, &count) != -1)
            {
                fprintf(stdout,"Child: count = %d\n",count);

                // allocate space for the byte we just read + the rest
                //  of whatever is on the pipe.
                buff = malloc(count+1);
                buff[0] = byte;
                if (read(fd[0], buff+1, count) == count)
                    fprintf(stdout,"Child: received \"%s\"\n", buff);
                free(buff);
            }
            else
            {   // could not read in-size
                perror("Failed to read input size.");
            }
        }

        // close our side
        close(fd[0]);
        fprintf(stdout,"Child: Shutting down.\n");
    }
    else
    {   // close read size. don't need it.
        const char msg1[] = "Message From Parent";
        const char msg2[] = "Another Message From Parent";
        close(fd[0]);
        sleep(5); // simulate process wait
        fprintf(stdout, "Parent: sending \"%s\"\n", msg1);
        write(fd[1], msg1, sizeof(msg1));
        sleep(5); // simulate process wait
        fprintf(stdout, "Parent: sending \"%s\"\n", msg2);
        write(fd[1], msg2, sizeof(msg2));
        close(fd[1]);
        fprintf(stdout,"Parent: Shutting down.\n");
    }
    return 0;
}

出力

Parent: sending "Message From Parent"
Child: count = 19
Child: received "Message From Parent"
Parent: sending "Another Message From Parent"
Parent: Shutting down.
Child: count = 27
Child: received "Another Message From Parent"
Child: Shutting down.
于 2013-03-04T08:27:26.900 に答える
1

あとだと思う

ioctl(fd[0], FIONREAD, &count);  
the count is 0.  

read(fd[0], buff, count) will get no data.  

try   
read(fd[0], buff, 10)
于 2013-03-04T08:07:58.000 に答える
1

問題は、パイプに書き込まれるバイト数を取得することです。fork()の直後に取得しています。読み取りプロセスが最初に実行される場合、データは含まれません(カウントはゼロになります)。書き込みプロセスが最初に実行される場合、いくつかのデータが含まれます。

子プロセスをもう一方の端にデータが書き込まれるまで待機させるにはどうすればよいですか?

パイプをブロッキングモードで開いたので、できるだけ多くのデータを読み取る必要があり、書き込まれたデータのサイズを取得しようとしないでください。


完全なメッセージを待つ変更された例を次に示します。

#include <stdio.h>
#include <sys/ioctl.h>
int main()
{
int pid;
FILE *fp;
fp = fopen("test.txt","w");
char *buff = malloc(1024);
int fd[2];
int count = 0 ;
pipe(fd);
pid = fork();
        if(pid == 0)
        {
                close(fd[1]);

                int i = 0;

                while ( i < 10 )
                {
                    fprintf(fp,"\n TIME before read: %s \n",__TIME__);
                    read(fd[0], buff+i, 1);
                    ++ i;
                }

                fprintf(fp,"Full message received!\nbuffer: %s\n TIME after read %s\n", buff, __TIME__);
        }
        else{
                close(fd[0]);
                sleep(10);    //delay caused by application specific code replaced with sleep
                write(fd[1],"THIS is it",10);
        }
fclose(fp);
return 0;
}
于 2013-03-04T08:06:34.073 に答える