首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >尝试使用循环创建可伸缩的管道和execvp程序

尝试使用循环创建可伸缩的管道和execvp程序
EN

Stack Overflow用户
提问于 2021-02-14 14:08:30
回答 1查看 55关注 0票数 1

该程序尝试使用多于一个的任意数量的命令,并使用管道、execvp和fork将它们链接在一起,就像shell一样。在这段代码中,我有一个硬编码的"ls“、" wc”和"less“,结果应该像在shell上运行"ls |wc| less”一样。由于某些原因,管道不能按预期工作。我在第99行有一大堆评论来解释我认为的问题所在(以"The read end of the...“开头)。我知道没有错误检查,任何帮助都是非常感谢的。

代码语言:javascript
复制
#include <iostream>
#include <string.h>
#include <string>
#include <vector>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

#define READ 0
#define WRITE 1

//This program will do three different commands ls, wc, then less.
int main(){
  pid_t pid;
  int cmd=3;
  //One less pipe than command is required.
  int fd[cmd-1][2];
  //The pipes are created in a for loop.
  for(int i=0; i<(cmd-1); i++){
    if(pipe(fd[i])==-1){
      cout<<"Help"<<endl;
    }
  }
  //The commands are put in c.
  char* c[3];
  c[0]="ls";
  c[1]="wc";
  c[2]="less";
  //First fork
  pid=fork();
  if(pid==0){

    //Pipe 0 is linked up.
    close(fd[0][READ]);
    dup2(fd[0][WRITE], 1);
    close(fd[0][WRITE]);

    //Remaining pipes are closed.
    for(int i=1; i<(cmd-1); i++){
      close(fd[i][READ]);
      close(fd[i][WRITE]);
    }

    //The command is prepared and then execvp is executed.
    char* temp[2];
    temp[0]=c[0];
    temp[1]=NULL;
    char* x=temp[0];
    execvp(x, temp);
  }

  //This for loop executes two times less than the number of commands.
  for(int i=0; i<(cmd-2); i++){
    pid=fork();
    if(pid==0){

      //I link up the read connection with pipe 0, I am fairly certain that
      //this part is working. You can put a cout after this pipe and it will
      //print that of command 1.
      close(fd[i][WRITE]);
      dup2(fd[i][READ], 0);
      close(fd[i][READ]);

      //This is the linking of pipe 1.
      close(fd[i+1][READ]);
      dup2(fd[i+1][WRITE], 1);
      close(fd[i+1][WRITE]);

      //This closes the remaining pipes, in this case there are none.
      for(int j=0; j<(cmd-1); j++){
    if(j==i || j==(i+1)){
      continue;
    }
    close(fd[j][READ]);
    close(fd[j][WRITE]);
      }

      //The command is prepared and executed
      char* temp[2];
      temp[0]=c[i+1];
      temp[1]=NULL;
      char* x=temp[0];
      execvp(x, temp);
    }
  }
  pid=fork();
  if(pid==0){

    //The read end of the final pipe is linked here.
    //THIS IS WERE THE PROBLEM IS! For some reason after dup2, I can no longer
    //use cin. Inbetween the linking of pipe 0 and pipe 1 (line 66), I can
    //use cin to make sure that the first execvp works and put its output in the
    //pipe. I also know that the second execvp works as intended. I just need to
    //know why dup2 messes up my program here.
    close(fd[cmd-2][WRITE]);
    dup2(fd[cmd-2][READ], 0);
    close(fd[cmd-2][READ]);

    //closes the remaining pipes.
    for(int i=0; i<(cmd-2); i++){
      close(fd[i][READ]);
      close(fd[i][WRITE]);
    }

    //Preps next command.
    char* temp[2];
    temp[0]=c[cmd];
    temp[1]=NULL;
    char* x=temp[0];
    execvp(x, temp);
    //}

  //closes all pipes.
  for(int i=0; i<(cmd-1); i++){
    close(fd[i][READ]);
    close(fd[i][WRITE]);
  }
  return 0;
}
EN

回答 1

Stack Overflow用户

发布于 2021-02-15 00:31:32

您的代码有多个问题,例如您没有为命令分配内存,您的代码似乎没有正确地包含在括号中

我修改了你的代码如下:

代码语言:javascript
复制
#include <iostream>
#include <string.h>
#include <string>
#include <vector>
#include <sys/types.h>
#include <unistd.h>
using namespace std;


//This program will do three different commands ls, wc, then less.
int main(){
  pid_t pid = 0;
  int cmd=3, i;
  //One less pipe than command is required.
  int fd[cmd-1][2];
  //The pipes are created in a for loop.
  for(int i=0; i<(cmd-1); i++){
    if(pipe(fd[i])==-1){
      cout<<"Help"<<endl;
    }
  }
  //The commands are put in c.
  char c[3][8] = {{'l', 's', '\0'}, {'w', 'c', '\0'}, {'l','e','s','s', '\0'}}, *temp[2];

  for(i = 0; i < cmd-1; i ++){
    pid = fork();
    if(pid == 0){
      if(i != 0){
        // read from previous fd
        close(fd[i-1][1]);
        dup2(fd[i-1][0], STDIN_FILENO);
        close(fd[i-1][0]);
      }
      // write to current fd
      close(fd[i][0]);
      dup2(fd[i][1], STDOUT_FILENO);
      close(fd[i][1]);
      temp[0] = c[i];
      temp[1] = NULL;
      execvp(c[i], temp);
      exit(0);
    }
    else{
      if(i != 0){
        // close unnecessary fds in parent
        close(fd[i-1][0]);
        close(fd[i-1][1]);
      }
    }
  }
  // the last command i.e. less here
  if(i > 0){
      close(fd[i-1][1]);
      dup2(fd[i-1][0], STDIN_FILENO);
      close(fd[i-1][0]);
  }
  temp[0] = c[i];
  temp[1] = NULL;
  execvp(c[i], temp);
  return 0;
}

如果对你有效,请让我知道!

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

https://stackoverflow.com/questions/66192884

复制
相关文章

相似问题

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