C Pipe:父级在子级结束之前从子级读取

Posted

技术标签:

【中文标题】C Pipe:父级在子级结束之前从子级读取【英文标题】:C Pipe: Parent to read from child before child ends 【发布时间】:2012-09-29 01:31:59 【问题描述】:

下面的代码显示了子进程如何写入管道端,然后父进程如何从另一端读取 . 我在试验代码后注意到的是,只有在子进程终止之后,父进程才能读取数据。

有没有办法在子进程调用 write() 之后强制父进程进入前台并立即读取数据?有没有办法在不终止孩子的情况下读取数据?

#include <stdio.h> /* For printf */
#include <string.h> /* For strlen */
#include <stdlib.h> /* For exit */

#define READ 0 /* Read end of pipe */
#define WRITE 1 /* Write end of pipe */
char *phrase = "This is a test phrase.";
main()
    int pid, fd[2], bytes;
    char message[100];

    if (pipe(fd) == -1)  /* Create a pipe */
        perror("pipe"); 
        exit(1); 
    
    if ((pid = fork()) == -1)  /* Fork a child */
        perror("fork"); 
        exit(1); 
    
    if (pid == 0)  /* Child, writer */
        close(fd[READ]); /* Close unused end */
        write(fd[WRITE], phrase, strlen(phrase)+1);
        close(fd[WRITE]); /* Close used end */
     
    else  /* Parent, reader */
        close(fd[WRITE]); /* Close unused end */
        bytes = read(fd[READ], message, sizeof(message));
        printf("Read %d bytes: %s\n", bytes, message);
        close(fd[READ]);  /* Close used end */
    

【问题讨论】:

你想让父母等待孩子的终止吗?因为您观察到父级仅在子级终止后才读取可能不正确。我认为您观察到的是在该程序终止后您没有返回 shell 提示符。这可以通过确保父级简单地解决使用wait调用等待子进程的终止。但是如果要确保子进程终止,只有在确定父进程已读取数据时,也可以这样做。你能请吗?让我知道具体是什么要求。 @Tanmoy 我想要的是让父母在孩子终止之前读取数据。我还希望父母在孩子白人进入管道后立即读取数据。 我在回答中解释了一些概念。 PL。让我知道这是否有帮助。PL。再次考虑您的第二个要求。在多道程序环境中,您可能没有任何可移植的解决方案。 【参考方案1】:

你说的不对。尝试在“子”部分关闭管道的写入端之前添加 sleep(120) 调用并运行您的应用程序。

【讨论】:

有点长的睡眠时间,你需要做的就是让出cpu,你不觉得吗?简单地调用 sched_yield() [假设在支持它的系统上运行,但在其他系统上类似的系统] 怎么样? 很长一段时间让 OP 输入ps 并按回车键)) 你是对的。你能检查我发布的另一个问题吗?我和这篇文章有同样的问题,但是如果我在关闭管道的写端之前添加睡眠,它不会读取,直到孩子被终止。 ***.com/questions/12657430/…【参考方案2】:

第一个可以使用一些同步技术来完成。意味着孩子应该等到父级读取数据或在您的代码中父级终止。我在用于此同步的代码中添加了第二个管道。

写入后的孩子只是等待从该管道读取并在读取中被阻塞。

函数 read 只会在父进程终止时返回(此处为 0),因为现在读取子进程将收到文件结束通知,这是由于父进程退出后管道在父进程中的写入结束。 (写端会在parent终止后自动关闭,我没有明确添加)

你的第二个要求

I also want the parent to read the data immediately after the child whites to
the pipe. 

为什么你认为这没有发生?应该总是有一些分钟的时间滞后。

#include <stdio.h> /* For printf */
#include <string.h> /* For strlen */
#include <stdlib.h> /* For exit */

#define READ 0 /* Read end of pipe */
#define WRITE 1 /* Write end of pipe */
char *phrase = "This is a test phrase.";
main()
  int pid, fd[2], bytes;
  char message[100];
  int fd1[2];
  char buffer[1];
  int ret;

  if (pipe(fd) == -1)  /* Create a pipe */
    perror("pipe");
    exit(1);
  
  if (pipe(fd1) == -1)  /* Create a pipe */
    perror("pipe");
    exit(1);
  
  if ((pid = fork()) == -1)  /* Fork a child */
    perror("fork");
    exit(1);
  
  if (pid == 0)  /* Child, writer */
    close(fd[READ]); /* Close unused end */
    close(fd1[WRITE]);/*Close write  end of the 2nd pipe*/
    write(fd[WRITE], phrase, strlen(phrase)+1);
    close(fd[WRITE]); /* Close used end */
    /*For synchronisation let the child try to
    read from the 2nd pipe. 
    The function read, will return 0 only when the
    parent terminates and in this we are
    not interested if at all anything read or not.
    The read statement below, will return only if the
    parent has terminated, thus ensures that the
    child terminates only after the parent*/
    ret = read(fd1[READ],buffer, 1);
  

else  /* Parent, reader */
    close(fd[WRITE]); /* Close unused end */
    close(fd1[READ]); /*Close read end of the 2nd pipe*/
    bytes = read(fd[READ], message, sizeof(message));
    printf("Read %d bytes: %s\n", bytes, message);
    close(fd[READ]);  /* Close used end */

   

【讨论】:

这是一个迟到的评论,但这段代码让我对我的小程序有了更多的了解:如何将数据从孩子发送到长度未知的父母。这种技术对我帮助很大。 (我的程序是用汇编语言编写的,所以我不放在这里,因为这是关于 C 编程的。【参考方案3】:

你应该初始化 fd[0]=0 和 fd[1]=0

【讨论】:

【参考方案4】:

以下代码演示,在孩子写入管道后,父母可以读取管道。不需要子进程关闭管道或终止。

#include <stdio.h> /* For printf */
#include <string.h> /* For strlen */
#include <stdlib.h> /* For exit */

#define READ 0 /* Read end of pipe */
#define WRITE 1 /* Write end of pipe */
char *phrase = "This is a test phrase.";
main()
    int pid, fd[2], bytes;
    char message[100];

    if (pipe(fd) == -1)  /* Create a pipe */
        perror("pipe"); 
        exit(1); 
    
    if ((pid = fork()) == -1)  /* Fork a child */
        perror("fork"); 
        exit(1); 
    
    if (pid == 0)  /* Child, writer */
        close(fd[READ]); /* Close unused end */
        write(fd[WRITE], phrase, strlen(phrase)+1);
        sleep(10);
        close(fd[WRITE]); /* Close used end */
        sleep(20);
     
    else  /* Parent, reader */
        printf( "child ipd = %d\n\r", pid);
        close(fd[WRITE]); /* Close unused end */
        bytes = read(fd[READ], message, sizeof(message));
        printf("Read %d bytes: %s\n", bytes, message);
        close(fd[READ]);  /* Close used end */
        sleep(10);
    

【讨论】:

以上是关于C Pipe:父级在子级结束之前从子级读取的主要内容,如果未能解决你的问题,请参考以下文章

悬停在子级上而对父级没有悬停效果[重复]

在子级循环中获取父级 json 数据。 (Laravel Vue js)

css父级没包住子级是怎么回事,我用firebug查看,确实在父级的div中,但是就是没有包括子级的内容

仅在 Safari 中 - 位置:固定子级在父级为位置时被切断:固定且溢出:隐藏

父级中的Java方法占位符在子级中使用[重复]

ReactJS - 更新后子级无法访问父级状态