将printf()重定向到另一个进程的STDIN

时间:2018-11-20 01:10:59

标签: redirect fork stdout dup2

我一直在尝试编写一些代码,以通过write(1,line,strlen(line))或STDOUT_FILENO将写入重定向到printf()到另一个进程的STDIN_FILENO 。另一个过程将是/usr/bin/less。尽管在此站点上进行了许多尝试,阅读了大量手册页并尝试了close()dup2()的每种组合,但似乎没有任何效果。

感谢您的帮助,谢谢。

#include  <fcntl.h>
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <sys/types.h>
#include  <sys/wait.h>
#include  <sys/stat.h>
#include  <termios.h>
#include  <unistd.h>
#define INPUT_END 1
#define OUTPUT_END 0
int main(int argc, char* argv[]){
   pid_t pid1;
   pid_t pid2;
   int fd1[2], fd2[2];
   int x;
   pipe(fd1);
   pipe(fd2);
   pid1 = fork();

   if (pid1 == -1) {
      fprintf(stderr, "pid error\n");
      exit(1);
   }

   if(pid1 == 0) {
      close(fd1[INPUT_END]);
      dup2(fd1[OUTPUT_END], STDIN_FILENO);
      close(fd1[OUTPUT_END]);
      close(fd2[OUTPUT_END]);
      dup2(fd2[INPUT_END], STDOUT_FILENO);
      close(fd2[INPUT_END]);
      execlp("less", "-r",(char*) NULL);

   }else {
      close(fd1[OUTPUT_END]);
      dup2(fd1[INPUT_END], STDOUT_FILENO);
      close(fd1[INPUT_END]);
      close(fd2[INPUT_END]);
      dup2(fd2[OUTPUT_END], STDIN_FILENO);
      close(fd2[OUTPUT_END]);

      for(x=0;x<100;x++) {
         write(STDOUT_FILENO, "AAA\n", 4);
         printf("AAA\n");
         fflush(stdout);
      }

      close(fd1[OUTPUT_END]);
      close(fd1[INPUT_END]);
      close(fd2[OUTPUT_END]);
      close(fd2[INPUT_END]);
      waitpid(-1, NULL, 0);
   }
}

1 个答案:

答案 0 :(得分:0)

您的程序完全按照您编写的程序进行操作:它创建两个管道和一个运行较少的子进程,使用管道将程序的stdout重定向到less的stdin并将less的stdout重定向到该程序的stdin。然后,它写入一堆数据(较少的数据将复制到其stdout-程序的stdin),然后等待更少的数据退出。但这将永远不会发生,因为等待更多输入的时间越来越少。

如果您想停止一切,则需要close(STDOUT_FILENO)才能调用waitpid -如果添加此内容,将会退出较少的内容,并且等待类型将返回,然后您的程序将继续(然后退出)。您仍然不会在终端上看到任何内容,因为没有任何内容写入终端-更少地写入程序的stdin(您从未读过)。

如果增加要写入的数据量,则会出现死锁-因为您从不读取stdin,所以一旦fd2管道填满,就会阻塞写入,然后减少fd1填满,程序就会块。但是,Linux上的默认管道尺寸非常大,因此将需要大量数据。

请注意,您也可以像使用cat一样使用less -当stdout不是终端时,less实际上会降级为cat

如果要输出数据到终端,使用less进行调解(在页面等之后停止),则需要将less的标准输出指向终端。只需从上面的代码中删除fd2和引用fd2的每一行,它就可以工作-尽管如果您close(STDOUT_FILENO)

仍然会挂在最后