簡體   English   中英

從 C 程序中執行程序

[英]Execute program from within a C program

我應該如何從我的C程序中運行另一個程序? 我需要能夠將數據寫入已啟動程序的STDIN (並且可能從它的STDOUT中讀取)

我不確定這是否是標准的 C function。 我需要應該在 Linux 下工作的解決方案。

你想使用popen 它為您提供了一個單向 pipe ,您可以使用它訪問程序的標准輸入和標准輸出。

popen 是現代 unix 和類 unix 操作系統的標准配置,其中 Linux 是其中之一:-)

類型

man popen

在終端中閱讀更多相關信息。

編輯

popen是否產生單向或雙向管道取決於實現。 LinuxOpenBSD中, popen產生單向管道,它們是只讀或只寫的。 OS X上, FreeBSDNetBSD popen產生雙向管道。

不久前,我為其他人編寫了一些示例 C 代碼,展示了如何執行此操作。 這是給你的:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

void error(char *s);
char *data = "Some input data\n";

main()
{
  int in[2], out[2], n, pid;
  char buf[255];

  /* In a pipe, xx[0] is for reading, xx[1] is for writing */
  if (pipe(in) < 0) error("pipe in");
  if (pipe(out) < 0) error("pipe out");

  if ((pid=fork()) == 0) {
    /* This is the child process */

    /* Close stdin, stdout, stderr */
    close(0);
    close(1);
    close(2);
    /* make our pipes, our new stdin,stdout and stderr */
    dup2(in[0],0);
    dup2(out[1],1);
    dup2(out[1],2);

    /* Close the other ends of the pipes that the parent will use, because if
     * we leave these open in the child, the child/parent will not get an EOF
     * when the parent/child closes their end of the pipe.
     */
    close(in[1]);
    close(out[0]);

    /* Over-write the child process with the hexdump binary */
    execl("/usr/bin/hexdump", "hexdump", "-C", (char *)NULL);
    error("Could not exec hexdump");
  }

  printf("Spawned 'hexdump -C' as a child process at pid %d\n", pid);

  /* This is the parent process */
  /* Close the pipe ends that the child uses to read from / write to so
   * the when we close the others, an EOF will be transmitted properly.
   */
  close(in[0]);
  close(out[1]);

  printf("<- %s", data);
  /* Write some data to the childs input */
  write(in[1], data, strlen(data));

  /* Because of the small amount of data, the child may block unless we
   * close it's input stream. This sends an EOF to the child on it's
   * stdin.
   */
  close(in[1]);

  /* Read back any output */
  n = read(out[0], buf, 250);
  buf[n] = 0;
  printf("-> %s",buf);
  exit(0);
}

void error(char *s)
{
  perror(s);
  exit(1);
}
  1. 使用pipe(...)創建兩個管道,一個用於stdin ,一個用於stdout
  2. fork(...)進程。
  3. 在子進程中( fork(...)返回 0 的那個) dup (...)stdin / stdout的管道。
  4. exec[v][e]子進程中要啟動的programm文件。
  5. 在父進程(其中fork返回子進程的 PID)執行一個循環,從子進程的stdoutselect(...)poll(...)read(...) )中讀取緩沖區,直到孩子終止( waitpid(...) )。
  6. 如果它期望一些,最終在stdin輸入上為孩子提供輸入。
  7. 完成后close(...)管道。

對於簡單的單向通信,popen() 是一個不錯的解決方案。 但是,它對雙向通信沒有用。

IMO,imjorge (Jorge Ferreira) 給出了雙向通信的大部分答案(80%?) - 但省略了一些關鍵細節。

  1. 父進程關閉用於向子進程發送消息的 pipe 的讀取端至關重要。
  2. 子進程關閉用於向子進程發送消息的 pipe 的寫入端至關重要。
  3. 父進程關閉用於向父進程發送消息的 pipe 的寫入端至關重要。
  4. 子進程關閉用於向父進程發送消息的 pipe 的讀取端至關重要。

如果您不關閉管道的未使用端,那么當其中一個程序終止時,您將不會獲得明智的行為; 例如,孩子可能正在從其標准輸入讀取,但除非 pipe 的寫入端在孩子中關閉,否則它將永遠不會獲得 EOF(讀取的零字節),因為它仍然有 pipe 打開並且系統認為它有時可能會開始寫 pipe,即使它當前掛起等待從中讀取內容。

寫入進程應考慮是否處理在沒有讀取進程的 pipe 上寫入時給出的 SIGPIPE 信號。

您必須了解 pipe 容量(取決於平台,可能只有 4KB)並設計程序以避免死鎖。

您可以使用系統調用,閱讀系統手冊(3)

我認為你可以使用

freopen

為了這。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM