UNIX中的管道不是单向的吗? [英] Aren't pipes in UNIX supposed to be uni-directional?

查看:78
本文介绍了UNIX中的管道不是单向的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看看下面的代码:

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

main() {
    int pipdes[2];
    char buff[50];
    const char parent[]="Parent Writes. Child Reads\n";
    const char child[]="Child Writes. Parent Reads\n";
    if(pipe(pipdes)==0) {
        pid_t pid=fork();
        if(pid<0)
              printf("Error\n");
        if(pid==0){
            read(pipdes[0],buff,50);
            printf("Parent: %s",buff);
            write(pipdes[1], child, strlen(child));
            exit(0);
        }
        else if(pid>0) {
            write(pipdes[1], parent, strlen(parent));
            wait(pid);
            read(pipdes[0], buff, 50);
            printf("Child: %s", buff);
        }
    }
    else
        printf("Error in pipe\n");
}

现在,在这里我只创建了一个管道,但是两个进程都可以读取和写入.管道不是单向的. 另外,当我将常规的"close(pipdes [0])"作为父项,而将"close(pipdes [1])"作为子项时,尽管我添加了open(pipdes [0])函数,但代码不起作用.以后.

Now, here I have created just one pipe, but both the processes can read and write from. Aren't pipes supposed to be uni-directional. Also, when i put the conventional 'close(pipdes[0])' for parent and 'close(pipdes[1])' for child, the code doesn't work, though I add the open(pipdes[0]) function later.

我对UNIX和管道的概念仍然很生疏,因此我在这里可能有些la脚,但是请提供帮助.

My concepts with UNIX and pipes is still raw, so I might come out a bit lame here, but please do assist.

推荐答案

在某些系统上,管道可以是双向的.但是它们不是必须的,并且任何关于它们将是不可移植的假设的.特别是它们不在Linux上.

On some systems, pipes can be bidirectional. But they don't have to be, and any assumption that they will be is non-portable. In particular, they aren't on Linux.

实际上,您的代码有问题-两个进程都试图读取和写入同一管道.管道的预期用途是孩子写而父母读,反之亦然.当前的处事方式现在对您有效,因为您正在阅读和书写一次,并且对孩子进行wait操作.但是,当您尝试以自己的方式做事时循环播放时,您将无法执行wait -并且如果没有同步,孩子通常会(但不总是如此!)最终会阅读打算发送给父母的内容,反之亦然.

As it is, your code has a problem -- both processes are trying to read from and write to the same pipe. The intended use for pipes is that the child writes and the parent reads, or vice versa. The current way you're doing things works for you right now, because you're reading and writing once and waiting on the child. But when you loop while trying to do things the way you're doing, you can't wait -- and without synchronization, the child will often (but not always!) end up reading what it intended to send to the parent, and vice versa.

如果希望数据双向流动,则可以使用两对管道.我们称它们为parent_pipechild_pipe.父级将从parent_pipe[0]读取并写入child_pipe[1],而子级将从child_pipe[0]读取并写入parent_pipe[1].

If you want data flowing in both directions, you could use two pairs of pipes. Let's call them parent_pipe and child_pipe. The parent would read from parent_pipe[0] and write to child_pipe[1], and the child would read from child_pipe[0] and write to parent_pipe[1].

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

int main() {
    int parent_pipe[2];
    int child_pipe[2];
    char buff[50];

    if(pipe(parent_pipe) || pipe(child_pipe)) {
        perror("pipe(...)");
        exit(1);
    }

    // As noted elsewhere, you're using `fork()` incorrectly.
    // `fork()` returns 0 to the child, and a pid to the parent, or -1 if an error
    // occurs.
    int pid = fork();
    if (pid == -1) {
        perror("fork()");
        exit(1);
    }

    if (pid == 0) {
        // this is the child process.  read from child_pipe, write to parent_pipe
        const char child[]="Child Writes. Parent Reads\n";
        int in, out;
        in = child_pipe[0];
        // in = parent_pipe[0];  // uncomment me to test with one pipe pair
        out = parent_pipe[1];

        for (int i = 0; i < 10; ++i) {
            read(in,buff,50);
            printf("Parent: %s",buff);
            // NOTE: `strlen(child)` doesn't include the nul at the end!
            write(out, child, strlen(child) + 1);
        }
    }
    else {
        // this is the parent process
        const char parent[]="Parent Writes. Child Reads\n";
        int in, out;
        in = parent_pipe[0];
        out = child_pipe[1];
        // out = parent_pipe[1];  // uncomment me to test with one pipe pair

        for (int i = 0; i < 10; ++i) {
            write(out, parent, strlen(parent) + 1);
            read(in, buff, 50);
            printf("Child: %s", buff);
        }
    }
}

或者,您可以使用一对用socketpair(AF_LOCAL, SOCK_STREAM, 0, sockdes)创建的UNIX套接字(其中sockdes是我们重命名了pipdes的名称,因为它现在是套接字,而不是管道).子级将读取和写入sockdes[0],而父级将读取和写入sockdes[1].反之亦然.

Alternatively, you could use a pair of UNIX sockets created with socketpair(AF_LOCAL, SOCK_STREAM, 0, sockdes) (where sockdes is what we renamed pipdes to, since it's sockets now and not pipes). The child would read from and write to sockdes[0], and the parent would read from and write to sockdes[1]. Or vice versa.

这篇关于UNIX中的管道不是单向的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆