首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与dup2的问题

与dup2的问题
EN

Stack Overflow用户
提问于 2022-03-27 23:07:55
回答 1查看 146关注 0票数 0

我正在尝试一个简单的程序,其中STDOUT从子进程指向父进程。如果我不多次分叉并在循环中调用child_processparent_process,程序就能工作。但是,当我在fork、child_processparent_process周围放一个for循环时,dup2函数返回-1,因此程序失败。我做错了什么?

这段代码在child_processparent_process周围有一个parent_process循环,并且与dup2有问题。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
 
#define BUFSIZE 256
 
void child_process(int pipe_pair[2]){
 
    // closes the child's STDOUT descriptor and replaces it with
    // the write pipe linked to the parent's read pipe
    if (dup2(pipe_pair[1], STDOUT_FILENO) == -1){ 
      // if dup2 fails, perror writes to stderr so this reports
      // appropriately either way as the child and parent share stderr
      perror("dup2"); 
      // parent will know if the child failed since we return 1
      // (ideally return errno so that calling processes know the error code)
      exit(EXIT_FAILURE); 
    }   
 
    // duplicated by dup2 above, no longer needed
    close(pipe_pair[1]); 
    // close read end as we will never read from stdout
    close(pipe_pair[0]); 
 
    // printf writes to stdout by default
    // we could also use fprintf(stdout, ...)
    printf("Hello, parent!\n"); 
    // make sure the write buffer is flushed before we exit
    fflush(stdout); 
 
    // close to make sure read() returns 0 in the parent
    close(STDOUT_FILENO); 
 
    // child exits
    exit(EXIT_SUCCESS); 
}
 
void parent_process(int pipe_pair[2], pid_t cpid){
 
    // cstatus will store the return of the child process
    // buf will hold the child's writes to stdout --
    // {0} initializes the array elements to 0x00
    int cstatus; 
    char buf[BUFSIZE] = {0}; 
 
    close(pipe_pair[1]); // we won't write to stdout
 
    // read until closed, or error (0 or -1, respectively)
    for (int n = 0; (n = read(pipe_pair[0], buf, BUFSIZE)) > 0;){ 
      printf("Received %d bytes from child process: ", n); 
      // (needed otherwise write() may output before 
      // printf since stdio output to stdout is line buffered)
      fflush(stdout); 
      // writes just what we read so no need to reset buf
      write(STDOUT_FILENO, buf, n); 
      printf("\n");
      fflush(stdout);
    }   
 
    // close read pipe
    close(pipe_pair[0]); 
 
    // waits for child process with pid 'cpid' to
    // return and stores the exit code in cstatus
    waitpid(cpid, &cstatus, 0); 
 
    printf("Child exit status was: %d\n", cstatus);
 
    // terminate parent
    //exit(EXIT_SUCCESS); 
 
}
 
int main(int argc, char **argv){
 
  // cpid stores the process id of the child process
  // stdout_pipe array = pipe descriptor pair -- 
  // [0] is the read end, [1] is the write end
  pid_t cpid; 
  int stdout_pipe[2]; 
 
  // call that creates the two unidirectional pipe streams 
  // and stores the descriptors in the array
  if (pipe(stdout_pipe) == -1){ 
    perror("pipe");
    exit(EXIT_FAILURE);
  }
 
  // fork happens here, cpid will have the child's
  // process id or -1 if the call fails
  for (int i=0; i<3; i++) {
      cpid = fork(); 
      if (cpid == -1){
         perror("fork");
         exit(EXIT_FAILURE);
      }
 
      // child (fork returns 0 in the child and the child ID for the parent)
      if (cpid == 0) 
         child_process(stdout_pipe);
      // else when cpid is not 0 or -1 we're in the parent
      else 
         parent_process(stdout_pipe, cpid);
  }
  // we shouldn't get here, but return int from main for correctness
  return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-27 23:26:22

问题是这个块在循环之外:

代码语言:javascript
复制
if (pipe(stdout_pipe) == -1){ 
  perror("pipe");
  exit(EXIT_FAILURE);
}

第一个对parent_process的调用关闭了管道描述符,并且它们不会在循环的第二次迭代中重新打开,因此dup没有任何内容。

最简单的解决方案是将pipe调用移到循环中。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71640957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档