使用 Pipes 和 exec() 控制另一个控制台应用程序

Posted

技术标签:

【中文标题】使用 Pipes 和 exec() 控制另一个控制台应用程序【英文标题】:Using Pipes and exec() to control another console application 【发布时间】:2016-06-23 21:13:08 【问题描述】:

我正在尝试自学一些重定向。我有以下问题:

我有一个简单的程序,它要求用户输入一个整数,然后输出一些其他整数,它会无限期地执行此操作,直到用户输入 0,然后关闭。

我正在尝试为该程序编写一个包装器,将来它可能是另一个控制台应用程序的一些 GUI 包装器。 目标是与该程序进行通信。

我的第一个想法是使用管道,分叉进程,将管道设置为子进程的标准输入和标准输出,然后 exec() 控制台应用程序。

现在,到目前为止,我的代码无法正常工作,因为控制台应用程序确实被执行,但它照常运行,在控制台中,输出没有到达我想要的位置。

main()

  int master_to_slave[2];
  int slave_to_master[2];

  pipe(master_to_slave);
  pipe(slave_to_master);

  int pid;

  if((pid=fork())==0)
     close(master_to_slave[1]);
     close(slave_to_master[0]);
     dup2(0, master_to_slave[0]);
     dup2(1, slave_to_master[1]);
     char *args[] =  NULL ;
     execv("/home/ebach/Documents/HIWI/random.exe",args);
  
  else if(pid<0)
    //ALARM ALARM
  
  else
     close(master_to_slave[0]);
     close(slave_to_master[1]);

    while(1)
      char buff[16];
      int rd = read(slave_to_master[0], &buff, sizeof(buff));
      if(rd > 0)
      buff[rd-1] = '\0';
      printf("Redirected: ");
      for(int i = 0; i < rd; i++)
    printf("T%c", buff[i]);
      
      printf("\n");
      
    
    wait(NULL);
  

到目前为止,它只是应该重定向控制台应用程序的输出。 (如您所见,它应该只添加 'Redirected:'

不管怎样,你可能看到我对c并不完全精通,所以我找不到错误。

我是否“连接”错了管道?

我遇到的另一个解决方案是通过使用 forkpty() 和 exec() 来使用伪终端,我应该走那条路吗?

提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

你使用了 dup2 倒退。根据man page:int dup2(int fildes, int fildes2);dup2 将导致filedes2 引用与filedes 相同的打开文件。

【讨论】:

另外,正确复制后,复制到标准流上的原始FD应该被关闭。【参考方案2】:

@hacatu 似乎在他的回答中确定了您的主要问题。此外,

正如我对 hacatu 的回答所评论的那样,一旦孩子 dup2()s 将管道末端连接到标准流之一,它应该关闭该管道末端。例如,
    dup2(slave_to_master[1], 1);
    close(slave_to_master[1]);
提供给execv()execvp() 的参数向量,以及提供给execl()execlp()execle() 的参数列表直接映射到目标程序的argv 向量。因此,通常至少有一个元素,命名正在执行的程序。一些程序依赖于此。例如:
    char *args[] =  "random.exe", NULL ;
    execv("/home/ebach/Documents/HIWI/random.exe", args);

不过,在这种情况下,您可能会发现 execl() 更方便一些:

    execl("/home/ebach/Documents/HIWI/random.exe", "random.exe", NULL);

【讨论】:

感谢您的意见,因为我不确定哪位高管适合我。现在,我正在努力解决另一个问题:奇怪的是,父进程似乎没有输出任何东西。显然错误不在于读取功能,因为它甚至没有到达它(据我所知,我插入了一些 printf() 函数来测试它。

以上是关于使用 Pipes 和 exec() 控制另一个控制台应用程序的主要内容,如果未能解决你的问题,请参考以下文章

Linux管道(Pipes)

使用运行时 exec() 传递控制字符 [重复]

进程控制---exec族函数

06Shell并发控制

切换视图控制器时的 EXEC_BAD_ACCESS (code=1 address=0x90000008)

如何在 php 中使用 exec 命令运行 codeigniter 控制器功能