11

这是一个例子来说明我的意思:

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

int main(void)
{
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!\n";
        char    readbuffer[80];

        pipe(fd);

        if((childpid = fork()) == -1)
        {
                perror("fork");
                exit(1);
        }

        if(childpid == 0)
        {
                /* Child process closes up input side of pipe */
                close(fd[0]);

                /* Send "string" through the output side of pipe */
                write(fd[1], string, (strlen(string)+1));
            exit(0);
    }
    else
    {
            /* 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("Received string: %s", readbuffer);
    }

   return(0);

}

但是,如果我的一个进程需要连续写入管道而另一个管道需要读取怎么办?

上面的例子似乎只适用于一次写入和一次读取。

4

5 回答 5

29

您的管道是单向流 - 每端都有一个文件描述符。不需要 close() 管道的任一端来允许数据通过它。

如果您的管道跨越进程(即在 fork() 之前创建,然后父子进程使用它进行通信),您可以有一个写入和一个读取端。然后最好关闭不需要的管道末端。这将

  • 确保当写入端关闭管道时,读取端可以看到它。例如,假设孩子是写方,它死了。如果父写端尚未关闭,则父端将不会从管道获得“eof”(零长度读取()) - 因为管道有一个打开的写端。
  • 明确哪个进程正在写入,哪个进程正在管道上读取。

如果您的管道跨越线程(在同一进程中),则不要关闭管道不需要的末端。这是因为文件描述符被进程持有,一个线程关闭它会关闭所有线程,因此管道将变得不可用。

没有什么可以阻止您让一个进程连续写入管道而另一个进程读取。如果这是您遇到的问题,请向我们提供更多详细信息以帮助您解决问题。

于 2009-06-10T14:52:23.547 回答
12

执行 fork 后,所有 fd 都被复制。每个进程的管道两端都打开。如果您只想使用一端,则应关闭另一端(如果您的进程写入,请关闭读取端)。

除了一个明显的事实,如果你不关闭描述符,操作系统将在打开的文件表中保留额外的条目,如果你不关闭管道的写端,阅读器将永远不会收到 EOF,因为仍然有一种进入的方式数据进入管道。AFAIK(和 IIRC)在其他进程中不关闭读取 fd 没有问题——也就是说,除了无缘无故打开文件之外。

还建议(作为一种好习惯,不要影响太大)在退出应用程序之前关闭所有描述符(即在每个进程中完成读/写操作后关闭管道的另一端)

于 2009-06-10T14:51:33.500 回答
0

管道不会为您提供双向通道,也不会多播。一个管道只有两个端,它没有一个写端和多个读端。

如果您想要许多阅读器,那么您需要与阅读器进程一样多的管道。

于 2009-06-10T14:59:56.540 回答
0

“上面的例子似乎只适用于一次写入和一次读取。”

那是因为在一次读写之后你的代码就退出了。您需要保持循环写入和循环读取以实现连续性。它似乎与 FD close 没有任何关系。正如之前的回复中提到的,您需要在每个进程上都有一个结束,以便关闭另一个。

我希望我理解正确的查询。

于 2009-06-11T10:48:16.457 回答
0

只用于同步,保证操作的原子性

于 2011-07-19T08:30:57.303 回答