Having issues with pipe, fork, dup2

2019-08-04 19:48发布

问题:

I am using pipes, fork , dup2 to implement “ls | more” or “ls | sort” etc. I am just not able to understand the issue here. When I run my program, I get this error:

./a.out  
Missing filename ("less --help" for help)

Why am I getting "less" ??

What is wrong with this code ? If I change “more” to “ls” again, it works fine. I mean, its like doing ls | ls.

#define STDIN 0
#define STDOUT 1

int main()
{
   int fd[2];
   int pid;
   char *lschar[20]={"ls",NULL};
   char *morechar[20]={"more",NULL};
   pid = fork();
   if (pid == 0) {
   /* child */
     int cpid;
     cpid = fork();
     if(cpid == 0) {
       //printf("\n in ls \n");
       pipe(fd);
       dup2(fd[1], STDOUT);
       close(fd[0]);
       close (fd[1]);
       execvp("ls",lschar);
     } else if(cpid>0) {
       waitpid(cpid, NULL,0);
       dup2(fd[0],STDIN);
       close(fd[0]);
       close(fd[1]);
       execvp("more", morechar);
     }
   } else if (pid > 0) {
     /* Parent */
     waitpid(pid, NULL,0);
   }
   return 0;
}

Appreciate your help.

回答1:

Your main problem lies in your placement of the pipe() call. You must call it before you fork():

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

#define STDIN 0
#define STDOUT 1

int main()
{
  int fd[2];
  int pid;
  char *lschar[20]={"ls",NULL};
  char *morechar[20]={"more", NULL};
  pid = fork();
  if (pid == 0) {
    /* child */
    int cpid;
    pipe(fd);
    cpid = fork();
    if(cpid == 0) {
      //printf("\n in ls \n");
      dup2(fd[1], STDOUT);
      close(fd[0]);
      close (fd[1]);
      execvp("ls",lschar);
    } else if(cpid>0) {
      dup2(fd[0],STDIN);
      close(fd[0]);
      close(fd[1]);
      execvp("more", morechar);
    }
  } else if (pid > 0) {
    /* Parent */
    waitpid(pid, NULL,0);
  }
  return 0;
}

Otherwise, the more process doesn't have the correct file descriptors. Further, the waitpid() in your more process is problematic and unnecessary (more will wait for input on its own). If ls had a particularly long output the pipe could get full causing ls to block on its writes. The result is a deadlock and it waits forever. Hence, I've also removed the offending waitpid() call.

Also, if you make a good practice of checking the return values of functions like pipe() and dup2() this error would have been much easier to find -- you would have seen that your dup2() was failing.



标签: c linux fork pipe