Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 不是';UNIX中的t管道应该是单向的吗?_C_Unix_Pipe - Fatal编程技术网

C 不是';UNIX中的t管道应该是单向的吗?

C 不是';UNIX中的t管道应该是单向的吗?,c,unix,pipe,C,Unix,Pipe,请查看以下代码: #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

请查看以下代码:

#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");
}
#包括
#包括
#包括
#包括
#包括
main(){
int-pipdes[2];
字符buff[50];
const char parent[]=“父写入。子读取\n”;
const char child[]=“子级写入。父级读取\n”;
if(管道(pipdes)==0){
pid_t pid=fork();
if(pid0){
写入(pipdes[1],父,strlen(父));
等待(pid);
读取(皮德斯[0],浅黄色,50);
printf(“子项:%s”,buff);
}
}
其他的
printf(“管道中的错误”);
}
现在,我只创建了一个管道,但两个进程都可以从中读取和写入。管道不应该是单向的吗。 此外,当我将常规的“close(pipdes[0])用于父级,将“close(pipdes[1])”用于子级时,代码不起作用,尽管我稍后添加了open(pipdes[0])函数


我对UNIX和管道的概念还不成熟,所以我在这里可能有点站不住脚,但请提供帮助。

在某些系统上,管道可以是双向的。但它们不一定非得如此,任何关于它们将是可移植的假设都是不可移植的。特别是,它们不在Linux上

实际上,您的代码有一个问题——两个进程都试图从同一个管道读写。管道的预期用途是子级写入,父级读取,反之亦然。你现在做事情的方式对你很有效,因为你只需要读一次写一次,然后等待孩子。但是,当您尝试按您正在做的方式进行循环时,您不能等待,如果没有同步,孩子通常(但不总是!)会阅读它打算发送给家长的内容,反之亦然

如果希望数据双向流动,可以使用两对管道。让我们称它们为
parent\u pipe
child\u pipe
。父级将从
父级管道[0]
读取并写入
子级管道[1]
,子级将从
子级管道[0]
读取并写入
父级管道[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);
        }
    }
}
#包括
#包括
#包括
#包括
#包括
int main(){
int母管[2];
int child_管道[2];
字符buff[50];
if(管道(父管道)|管道(子管道)){
perror(“管道(…)”);
出口(1);
}
//正如其他地方所指出的,您使用的'fork()'不正确。
//`fork()`将0返回给子级,将pid返回给父级,如果出现错误,则返回-1
//发生。
int-pid=fork();
如果(pid==-1){
perror(“fork()”);
出口(1);
}
如果(pid==0){
//这是子进程。读取子管道,写入父管道
const char child[]=“子级写入。父级读取\n”;
int-in,out;
in=子管道[0];
//in=parent_pipe[0];//取消注释我以使用一个管道对进行测试
out=母管道[1];
对于(int i=0;i<10;++i){
读取(输入,浅黄色,50);
printf(“父项:%s”,浅黄色);
//注意:`strlen(child)`结尾不包括nul!
写(写,孩子,斯特伦(孩子)+1);
}
}
否则{
//这是父进程
const char parent[]=“父写入。子读取\n”;
int-in,out;
in=父管道[0];
out=子管道[1];
//out=parent_pipe[1];//取消注释我以使用一个管道对进行测试
对于(int i=0;i<10;++i){
写入(输出、家长、斯特伦(家长)+1);
读取(输入,浅黄色,50);
printf(“子项:%s”,buff);
}
}
}

或者,您可以使用一对使用
socketpair(AF\u LOCAL,SOCK\u STREAM,0,sockdes)
创建的UNIX套接字(其中
sockdes
是我们将
pipdes
重命名为的,因为它现在是套接字,而不是管道)。孩子将读写
sockdes[0]
,而家长将读写
sockdes[1]
。反之亦然。

不,它们不是。有些系统具有双向管道(sun、IIRC)。如果确实需要双向管道,可以使用socketpair()。

在POSIX.1-2001中,管道是单向的。从手册页:

pipe()创建一对文件描述符,指向管道索引节点, 并将它们放置在filedes指向的数组中。filedes[0]用于 读取时,filedes[1]用于写入


顺便说一下,您使用的
fork
是错误的:
fork
为父对象返回
pid>0
,为子对象返回
pid==0
pid不应该是
pid==0
,而不是
pid是的,很抱歉。我没有正确地复制代码。好吧,这正是我无法理解的,除了PID,那是因为(1)你在等待孩子。通常,您只需读取输入;使用
等待
,您正在写作,等待孩子读写,然后阅读。目前这是可行的,但是(2)您只进行了一次读/写迭代(这就是为什么
wait(pid)
有效)。在循环中,
wait
不起作用——它只会在孩子死后返回。如果你读写…比如说…50次,很有可能一对管道,孩子会读它刚刚发送给家长的内容,反之亦然。等一下,让我编辑一下。你的意思是,如果只需要发送和接收一条消息,那么管道就可以双向工作。这意味着管道通常不是单向的,只是在大多数情况下不方便双向使用。不,两个进程可以共享同一个管道这一事实并不意味着它们是双向的。如果它们是双向的,则子级可以从管道[0]读取并写入管道[1],父级可以写入管道[0]并从管道[1]读取。您当前拥有的是两个进程共享一个单向管道,这种方式碰巧是半偶然工作的。OK。所以这是同一个管道工作uni di