【问题标题】:Two way pipe communication between parent and child父子之间的双向管道通信
【发布时间】:2014-03-04 17:07:58
【问题描述】:

我正在尝试使用 C 中的 2 个管道在父进程和子进程之间创建双向通信。在 child1 中运行的 prog1 之后我想从 prog1 读取 3+4+5,然后用 write 向 prog1 发送一些东西,但我不能。 哪里错了?

/* prog1.c */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void
main(void){
    int FD;
unsigned int buf;
char buf[15];

printf("7+5+11=?\n");
FD=read(0,buf,10);
if(FD<0){
    perror("FAIL\n");
exit(EXIT_FAILURE);
}
     printf("TAKED:%s\n",buf);
}

prog2.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
void ERR_SYS(const char *msg);
int
main(void){
    char buf[15];
    int pipe1[2];
    int pipe2[2];
    pid_t childpid;

    memset(buf,'\0',14);

    if(pipe(pipe1) < 0 || pipe(pipe2) < 0)
     ERR_SYS("fail_pipe");

    if((childpid = fork()) < 0)
     ERR_SYS("fail_fork");

    if(childpid==0)
    {
      dup2(pipe2[1],1);
          dup2(pipe1[0],0);
      close(pipe1[1]);
          close(pipe2[0]);
      close(pipe2[1]);
      close(pipe1[0]);
          //close(1);
          //close(0);
      execle("./prog1",NULL,NULL,NULL);
    }else{

     close(pipe1[0]);
     close(pipe2[1]);
     read(pipe2[0],buf,4); /*I hope to read 3+4+5*/
     printf("BuF::%s\n",buf);
     write(pipe1[1],"off",3);/*send {off}*/
     wait(NULL);
    }
 return 0;
 }

 void 
 ERR_SYS(const char *msg)
 {
     perror(msg);
     exit(EXIT_FAILURE);
 }

【问题讨论】:

  • 检查读写的返回值! “我不能”是什么意思?程序表现如何?

标签: c linux exec fork pipe


【解决方案1】:

你的程序有几个问题:

  1. 您没有在 prog2.c 中检查 read、write 和 execle 的返回值
  2. 您正在发送“7+5+11=?\n”字符串,它有 10 个字符长,但只需要 4 个字符(3+4+5 甚至不是 4 个字符)。
  3. 您发送的“off”也是 3 个字符长,但不包括空终止符。
  4. 当您从fd 读取时,在这两种情况下都不会得到以空字符结尾的字符串,然后您会尝试使用printf 它。这是未定义行为的快速方法。在从任何文件描述符中读取的缓冲区末尾放置一个 '\0'!
  5. 尤其是read 返回的内容非常重要,因为它告诉您读取了多少个字符。您永远不应忽略 read 的返回值(在某些情况下与 write 函数相同)。

下次也提供一些你的程序的输出,因为提供一些帮助会更容易。

【讨论】:

  • 其他问题 -- printf 默认情况下只是缓冲稍后要写入的数据 -- 您需要显式调用 fflush 以确保其实际写入。这就是导致程序挂起的原因——孩子和父母都被阻止在read 中等待,并且两者都没有实际写入数据。但是在添加fflush 之后,你会遇到这里发现的所有其他问题......
【解决方案2】:

我在设置管道时没有遵循您的所有逻辑,因此我修改并希望澄清您的原始内容。我应该注意,无论出于何种原因,我从外部程序 (prog1) 的角度命名了 fd_in 和 fd_out(例如,fd_out 是 prog1 正在写入的位置,fd_in 是 prog1 正在读取的位置)。

这是我的 prog3.c 的内容:

...
#define READ_END 0
#define WRITE_END 1
void ERR_SYS(const char *msg);
int main(void) {

    char buff[15];
    char *msg = "hello";
    int fd_out[2];
    int fd_in[2];
    int nbytes;
    pid_t childpid;

    if(pipe(fd_out) < 0 || pipe(fd_in) < 0) {
            ERR_SYS("fail_pipe");
    }

    if((childpid = fork()) < 0) { 
            ERR_SYS("fail_fork");
    }

    if(childpid==0) { //child 
            //connect the write end of fd_out to stdout
            dup2(fd_out[WRITE_END], STDOUT_FILENO);
            close(fd_out[WRITE_END]);
            //connect the read end of fd_in to stdin
            dup2(fd_in[READ_END], STDIN_FILENO);
            close(fd_in[READ_END]);
            //the exec'd prog1 will inherit the streams
            execlp("./prog1", "prog1", NULL); //TODO: check return
    } else { //parent
            nbytes = write(fd_in[WRITE_END], msg, strlen(msg));
            //TODO: handle any errors from write
            nbytes = read(fd_out[READ_END],buff,sizeof(buff)-1);
            //TODO: handle any errors from read
            buff[nbytes] = '\0';
            printf("contents of buff::%s",buff);
    }
    return 0;
}
void ERR_SYS(const char *msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

这是我的 prog1.c 的内容

int main(void){
    char buff[15];
    int nbytes;
    nbytes = read(STDIN_FILENO, buff, sizeof(buff)-1);
    buff[nbytes] = '\0';
    printf("%s world\n", buff);
    return 0;

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 2015-06-13
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多