在使用dup2()重定向stdin后调用execve()时会发生什么?

时间:2015-11-26 16:34:58

标签: c linux shell

我正致力于模拟迷你版的shell。当用管道执行程序时,有些东西让我感到困惑。我学习了fork(),execve(),pipe()和dup2()。我以为我可以调用pipe()来构建一个未命名的管道,然后使用fork(),然后使用dup2()将标准输出重定向到管道的写入端,使用execve()来运行目标程序。当谈到第二个程序时,我可以将标准输入重定向到管道的读取端,并输出回原始的std-output,然后使用execve()来运行目标。但事实上,当我使用' ls -l'作为第一个节目,' wc -l'作为第二个,它失败了。但是,如果第二个是“猫”,它就会正常工作。那么,在使用dup2()重定向stdin后调用execve()时发生了什么?或者我的程序还有其他问题?

更新:我发布了一些用于验证我的想法的代码。就这个。 更重要的是,我没有使用waitpid()来确保这些事情按顺序运行。

int fd[2];

int main(int argc, char **argv, char **envp) {
    int fd[2];
    pipe(fd);
    int sfd[2];
    sfd[1] = dup(STDOUT_FILENO);
    sfd[0] = dup(STDIN_FILENO);
    int pid;

    pid = fork();
    if (pid == 0) {
        // child
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        close(fd[1]);
        char *cmd[] = {
            "/usr/bin/ls", "-l", NULL
        };
        execve("/usr/bin/ls", cmd, envp);
    } else {
        // parent
        int status;
        waitpid(pid, &status, 0);
    }

    pid = fork();
    if (pid == 0) {
        // child
        //dup2(fd[1], STDOUT_FILENO);
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        char *cmd[] = {
            "/usr/bin/wc", "-l", NULL
        };
        execve("/usr/bin/wc", cmd, envp);
    } else {
        // parent
        int status;
        //waitpid(pid, &status, 0);
    }

    /*pid = fork();
    if (pid == 0) {
        // child
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        char *cmd[] = {
            "/usr/bin/wc", "-l", NULL
        };
        execve("/usr/bin/wc", cmd, envp);
    } else {
        // parent
        int status;
        //waitpid(pid, &status, 0);
    }*/


    return 0;
}

1 个答案:

答案 0 :(得分:1)

“失败”是什么意思?

如果我尝试我得到:

void sort(int *, int);

int main() {
  int Array[10]={2,4,3,11,0,12,88,99,111,-15};
  int i, n=0, k=0, x=0, y=0;
  for(i=0;i<10;i++) {
    if(Array[i]%2==0) {
      n++;
    } else {
      k++;
    }
  }
  int ArrEven[n], ArrOdd[k];
  for(i=0;i<10;i++) {
    if(Array[i]%2==0) {
      ArrEven[x++]=Array[i];
    } else {
      ArrOdd[y++]=Array[i];
    }
  }
  sort(ArrEven, n);
  sort(ArrOdd, k);
  x=0;
  for(i=0;i<n;i++) {
    Array[i]=ArrEven[i];
  }
  for(i=0;i<k;i++) {
    Array[i+n]=ArrOdd[i];
  }

  for(i=0;i<10;i++) {
    printf("%d\n", Array[i]);
  }
  return 0;
}

void sort(int *array, int n) {
  for (int c = 0 ; c < ( n - 1 ); c++) {
    for (int d = 0 ; d < n - c - 1; d++) {
      if (array[d] > array[d+1]) {
        int swap = array[d];
        array[d] = array[d+1];
        array[d+1] = swap;
      }
    }
  }
}

这是因为/usr/bin/wc: standard input: Input/output error 1 不在我系统的ls中:

/usr/bin

如果我解决了这个问题,我会:

$ which wc cat ls
/usr/bin/wc
/bin/cat
/bin/ls

作为我的输出。