2015-10-16 67 views
1

我试图在shell中创建管道来重定向标准流,现在我被卡住了。重定向标准流

当我尝试运行此代码:

int fd[2]; 
pid_t pid; 

pipe(fd); 

pid = fork(); 
if (pid == 0) 
{ 
    // child process 

    // redirect standard input and output 
    dup2(fd[1], STDOUT_FILENO); 
    dup2(fd[0], STDIN_FILENO); 

    // close them (they are now redirected) 
    close(fd[0]); 
    close(fd[1]); 

    char *input_argv[] = {"/bin/ls", "/bin/ls", ">", "out.txt", NULL}; 

    execv(input_argv[0], input_argv); 
} 
else if (pid > 0) 
{ 
    // parent process 

    waitpid(pid, NULL,0); 
} 

我得到这个错误信息:

/bin/ls: cannot access >: No such file or directory 
/bin/ls: cannot access out.txt: No such file or directory 

我不知道他们是什么意思,是什么原因,以及如何解决这些问题。

我在做什么错?

回答

2

总而言之,代码没有任何意义。我认为最好的答案可以在这里给出的解释最有问题的部分:

// redirect standard input and output 
    dup2(fd[1], STDOUT_FILENO); 
    dup2(fd[0], STDIN_FILENO); 

fd[0]是读取结束,fd[1]管道的书写端。无论您写给fd[1]是否可在fd[0]上阅读。所以,这只是“短路”你的stdio流,根本不是有用的东西。

你想管做的通常是具有每父子进程(如之间的通信方向的管的孩子应该从父母阅读:在孩子dup2()阅读结束STDIN_FILENO并写入到从书写结束父母)。

char *input_argv[] = {"/bin/ls", "/bin/ls", ">", "out.txt", NULL}; 

现在这也没有意义。 A >告诉shell打开一个写入文件,并且exec()已经存在重定向STDOUT_FILENO的孩子。肯定是而不是在这里可以被ls理解。你没有一个外壳,你直接exec()ls

如果你的初衷是为了模仿给出

ls > out.txt 
壳时会做什么

你应该打开文件out.txt写入和孩子码dup2()之前,你打开的文件的文件描述符STDOUT_FILENOexec() ing ls。在这个场景中不需要管道。


编辑如果你想了解什么壳内部确实为ls > out.txt

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <sys/wait.h> 
#include <fcntl.h> 
#include <unistd.h> 

int main(void) 
{ 
    /* open file for writing */ 
    int outfd = open("/tmp/out.txt", O_CREAT|O_WRONLY, 00666); 
    if (outfd < 0) 
    { 
     perror("open()"); 
     return EXIT_FAILURE; 
    } 

    /* fork child */ 
    int pid = fork(); 
    if (pid < 0) 
    { 
     perror("fork()"); 
     return EXIT_FAILURE; 
    } 

    if (pid == 0) 
    { 
     /* in the child, redirect stdout to our file */ 
     if (dup2(outfd, STDOUT_FILENO) < 0) 
     { 
      perror("dup2()"); 
      return EXIT_FAILURE; 
     } 
     close(outfd); 

     /* then execute 'ls' */ 
     execlp("ls", "ls", 0); 

     /* only reached when execlp() fails: */ 
     perror("execlp()"); 
     return EXIT_FAILURE; 
    } 

    /* we don't need the output file in the parent process: */ 
    close(outfd); 

    /* wait for child to complete */ 
    int childrc; 
    waitpid(pid, &childrc, 0); 

    /* return exit code of child process */ 
    return childrc; 
} 

当然,实际的壳的代码看起来不同的(没有硬编码名称,使用execv*函数族,因为它不提前知道参数的数量,等等。)