【问题标题】:Simple shell with pipe( ) function带有 pipe() 函数的简单外壳
【发布时间】:2014-11-06 20:15:21
【问题描述】:

我正在编写一个简单的代码来实现 unix/linux shell 的管道功能。

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

void
cisshPipe(char* command1[], char* command2[])

{
  int fd[2];//create array for two file descritors 
  pid_t childPid;//To set for child process
  pipe(fd);//To create pipeline here

  if((childPid=fork())==-1)
  {
       perror("fork here");
       exit(1);
  }

//The below is the real meat for this subroutine
  if(childPid==0)//If child process
  {
     close(fd[0]);//To close the input of child
     dup(fd[0]);//To duplicate the input, for the later process
  }
  else//For the real output
  {
    close(fd[1]);//To close the parent output first
    execvp(command2[],command2);
  }

  }

但是,对于此处的预期表达式,我在“execvp(command2[],command2)”上遇到了一些编译错误。我认为这是由于我用来将子输出传递给父输入的 dup() 函数。请问有什么解决办法吗?

一些更新:

感谢约翰的回答。我修复了编译问题。但是当我输入“ls | sort”时它正在执行管道功能,我认为这里仍然是dup()的传递问题。

【问题讨论】:

  • 请发布确切的消息。错误是告诉你什么是错误的......
  • 感谢您的回复。立即修复。
  • 您是否阅读过您正在调用的函数的文档,例如execvp(3)?您应该按照记录调用它...

标签: c bash shell


【解决方案1】:
execvp(command2[],command2);

空的[] 是语法错误。也许你的意思是:

execvp(command2[0], command2);

【讨论】:

    【解决方案2】:

    此代码有效,但并未进行所有可能的错误检查。与将标准输入从(或标准输出)重定向到文件后需要关闭文件描述符的方式类似,当您使用管道时,如果您将管道的一端 dup()dup2() 指向标准输入或输出,您需要在执行命令之前关闭管道的两端。当管道在子进程中存在的父进程中创建时,您需要确保管道的两端也在父进程中关闭。

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/wait.h>
    #include <unistd.h>
    
    static inline void error(const char *msg)
    {
        perror(msg);
        exit(EXIT_FAILURE);
    }
    
    static void
    cisshPipe(char **command1, char **command2)
    {
        int fd[2];
        pid_t childPid;
        if (pipe(fd) != 0)
            error("failed to create pipe");
    
        if ((childPid = fork()) == -1)
            error("failed to fork");
    
        if (childPid == 0)
        {
            dup2(fd[1], 1);
            close(fd[0]);
            close(fd[1]);
            execvp(command1[0], command1);
            error("failed to exec command 1");
        }
        else
        {
            dup2(fd[0], 0);
            close(fd[0]);
            close(fd[1]);
            execvp(command2[0], command2);
            error("failed to exec command 2");
        }
    }
    
    int main(void)
    {
        char *ls[] = { "ls", 0 };
        char *sort[] = { "sort", "-r", 0 };
        cisshPipe(ls, sort);
        return 0;
    }
    

    样本输出:

    xx.dSYM
    xx.c
    xx
    xma.dSYM
    xma.c
    xma
    ws-c11.c
    …
    am-pm.pl
    2dv.dSYM
    2dv.c
    2dv
    2da.dSYM
    2da.c
    2da
    

    【讨论】: