管道末端的重定向(C shell)

时间:2017-11-24 18:21:25

标签: c shell unix pipe io-redirection

我正在尝试ls | tr a b > text.txt 我已完成管道,但我不能将STDOUT添加到管道的末尾(在我的情况下STDOUT只能在最后一个参数中)

我标记了代码中应该进行重定向的部分,我认为应该打开该文件,并使用dup2方法,但我不知道以哪种方式

方法包含管道 -

enum reqType { PIPE, STDOUT };

int spawn_proc (int in, int out, char** cmd) {
    pid_t pid;

    if ((pid = fork ()) == 0) {
        if (in != 0) {
          dup2 (in, 0);
          close (in);
        }
        if (out != 1) {
          dup2 (out, 1);
          close (out);
        }

      return execvp (cmd[0], cmd);
    }

  return pid;
}

void fork_pipes (int n, char** cmd[], enum reqType type) {
  int i;
  pid_t pid;
  int in, fd [2];

  in = 0;

  for (i = 0; i < n - 1; ++i) {
      if(type == PIPE || i < n-2) {
        pipe (fd);

        spawn_proc (in, fd [1], cmd[i]);

        close (fd [1]);

        in = fd [0];
      }
      else if(type == STDOUT && i == n-2) {
            ///HOW TO IMPLEMENT THIS PART?
      }
    }

  if (in != 0)
    dup2 (in, 0);

  execvp (cmd[i][0], cmd[i]);
}

EDIT 在标记为///的地方我写了

pipe(fd);
int out = open(cmd[n-1][0],O_WRONLY|O_CREAT|O_TRUNC);
spawn_proc(in, out, cmd[i]);
close(fd[1]);

1 个答案:

答案 0 :(得分:2)

  

我认为应该打开该文件,并使用dup2方法,但我不知道以哪种方式

您对实现重定向的机制是正确的。它应该在针对tr的过程中完成,并且在执行叠加之前。

让我们一步一步走:

ls | tr a b > text.txt

首先创建一个管道,然后fork()

从现在开始,两个进程并行运行,它们最终将通过{{1} 重叠 }:一个使用exec()程序,另一个使用ls程序。

tr的处理:

  1. 关闭管道的读取端:此过程只会写入管道。
  2. ls管道的写入结束dup2():此进程写入STDOUT的内容正被写入管道。
  3. 使用STDOUT执行叠加:exec()
  4. ls的处理:

    1. 关闭管道的书写结束:此过程只会从管道中读取。
    2. tr管道的读取结束dup2():此进程从STDIN读取的内容来自管道。
    3. 为了对STDIN文件执行重定向,首先text.txt文件open()进行写入并使用标记{{1然后text.txt获取的文件描述符O_CREAT

    4. 使用O_TRUNC执行叠加:dup2()

    5. 请注意,如果该命令附加到STDOUT而不是截断它(即:使用exec()而不是tr):

      text.txt

      >> >文件时,您必须使用标记ls | tr a b >> text.txt 而不是O_APPEND

      代码段

      我修改了你的代码(也是O_TRUNC的界面)。这是一个最小的例子,我希望它有所帮助。

      open()

      正如this comment中已经指出的那样。您只需在示例中调用text.txt一次:fork_pipes()系统调用只需要为每个管道运算符调用一次(即:复合命令中找到的#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int spawn_proc (int in, int out, char** cmd) { pid_t pid; if ((pid = fork ()) == 0) { if (in != 0) { dup2 (in, 0); close (in); } if (out != 1) { dup2 (out, 1); close (out); } return execvp (cmd[0], cmd); } return pid; } void fork_pipes (char** cmd[], const char *redirection) { int i, n; int in, out, fd[2]; in = 0; // obtain n from the NULL terminated cmd array for (n = 0; cmd[n]; ++n) ; // process all but the last elemet of the pipe for (i = 0; i < n-1; ++i) { pipe(fd); spawn_proc(in, fd[1], cmd[i]); close(fd [1]); in = fd [0]; } // process the last element of the pipe if (redirection) { out = open(redirection, O_WRONLY | O_CREAT | O_TRUNC); fchmod(out, 0666); } else out = STDOUT_FILENO; if (in != 0) dup2(in, 0); spawn_proc(in, out, cmd[i]); } int main() { char *cmd1[] = {"ls", NULL}; char *cmd2[] = {"tr", "a", "b", NULL}; char **cmd[] = { cmd1, cmd2, NULL}; // redirected to text.txt fork_pipes(cmd, "text.txt"); // no redirection fork_pipes(cmd, NULL); // another example with a longer pipe { char *cmd1[] = {"echo", "hello world", NULL}; char *cmd2[] = {"tee", NULL}; char *cmd3[] = {"tee", NULL}; char *cmd4[] = {"tr", "lo", "10", NULL}; char **cmd[] = {cmd1, cmd2, cmd3, cmd4, NULL}; // redirected to redirection.txt fork_pipes(cmd, "redirection.txt"); // no redirected fork_pipes(cmd, NULL); } return 0; } 字符)。例如,在以下命令中:

      pipe()

      pipe()必须完全调用四次,因为有四个管道运算符