【问题标题】:Subprocess commands in C++C++ 中的子进程命令
【发布时间】:2014-06-13 08:36:11
【问题描述】:

我有两个 C++ 程序:Program1 和 Program2。我想要做的是让 Program1 运行它的算法来计算它需要的任何东西,然后将所有计算出的信息传递到 Program2 中,让它使用 Program1 的输出运行它的算法。

如果我可以直接通过管道传输信息并关闭 Program1 而不必等待 Program2 先完成,那就太好了。类似于 python 中的subprocess.call()

【问题讨论】:

  • 您可能会发现highscore.de/boost/process 很有用。虽然不能说太多,但我从未使用过它。如果解决方案不必是可移植的,那么旧的fork(甚至system)可能会这样做。
  • 您可能会觉得有用的函数是:forkexecdup2writeread
  • 使用popen(3),听起来它会满足您的需求。它比pipe/fork/dup2/exec 组合更容易使用。
  • 你想模拟shell管道Program1 | Program2吗?这里Program1 可以在写完结果后立即退出。整个管道等待Program2 退出。您可以将管道放在后台,这样您就可以在同一个 shell 中运行其他命令,而无需等待 Program2 完成。你需要吗?

标签: c++ subprocess pipe


【解决方案1】:

要模拟subprocess.check_call("Program1 | Program2", shell=True) Python 调用,您可以使用system(3) in C

/** $ gcc simple-pipe-system.c && ./a.out */
#include <stdlib.h>

int main(void) {
  return system("Program1 | Program2");
}

下面是如何使用低级 pipe(2)/fork(2)/execlp(2) in C 模拟 Program1 | Program2 管道以进行比较:

/** $ gcc simple-pipe.c && ./a.out */
#include <sys/types.h> /* pid_t */
#include <unistd.h>

int main(void) {
  int fd[2]; /* pipe ends */
  pid_t pid = -1;

  if (pipe(fd) == -1)
    Report_error_and_exit("pipe");

  if ((pid = fork()) == -1)
    Report_error_and_exit("fork");
  else if (pid == 0)  {
    /* child: run Program1, redirecting stdout to the pipe */
    is_child = 1;
    Close(fd[0]); /* close unused read end of the pipe */

    /* redirect stdout */
    Redirect(fd[1], STDOUT_FILENO);

    /* run Program1 with redirected stdout */
    execlp("Program1", "Program1", NULL);
    Report_error_and_exit("execlp");
  }

  /* parent: run Program2, redirecting stdin to the pipe */
  Close(fd[1]); /* close unused write end of the pipe */

  /* redirect stdin */
  Redirect(fd[0], STDIN_FILENO);
  /* run Program2 with redirected stdin */
  execlp("Program2", "Program2", NULL);
  Report_error_and_exit("execlp");
}

其中 Report_error_and_exit、Close、Redirect 可以定义为:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>

#define Close(FD) do {                                          \
    const int Close_fd = (FD);                                  \
    if (close(Close_fd) == -1)                                  \
      fprintf(stderr, "%s:%d: close(" #FD ") %d: %s\n",         \
          __FILE__, __LINE__, Close_fd, strerror(errno));       \
  }while(0)

#define Report_error_and_exit(msg) do {                       \
    fprintf(stderr, "%s:%d: %s: %s\n", __FILE__, __LINE__,    \
        (msg), strerror(errno));                              \
    (is_child ? _exit : exit)(EXIT_FAILURE);                  \
  } while(0)
static int is_child = 0;

#define Redirect(FROM, TO) do {            \
    const int from = (FROM);               \
    const int to = (TO);                   \
    if (from != to) {                      \
      if (dup2(from, to) == -1)            \
        Report_error_and_exit("dup2");     \
      else                                 \
        Close(from);                       \
    }                                      \
  } while(0)

【讨论】:

    【解决方案2】:

    你会想要按照以下方式做一些事情:

    #include <unistd.h>
    
    int main () {
      // Do stuff for program1
      int pipefds[2];
      if (pipe (pipefds))
        throw 1;
      // Use ``write'' to send binary data to pipefds[0]
      dup2 (pipefds[1], 0);
      execl (/* Put the program2 arguments you want here. */);
      return 1;
    }
    

    有了这个,你只需要让 program2 从标准输入中读取所有必要的数据,你就完成了。

    【讨论】:

    • dup2 (pipefds[1], 0) 究竟做了什么...?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-19
    • 2014-03-26
    • 2014-07-16
    • 1970-01-01
    • 2017-08-28
    • 2021-12-10
    相关资源
    最近更新 更多