从C程序中执行程序

Sim*_*mon 8 c linux

我应该如何从我的C程序中运行另一个程序?我需要能够将数据写入STDIN已启动的程序(并且可以从中读取STDOUT)

我不确定这是否是标准的C函数.我需要在Linux下运行的解决方案.

fre*_*ace 17

你想用popen.它为您提供了一个单向管道,您可以使用它来访问程序的stdin和stdout.

popen是现代unix和unix-like操作系统的标准配置,其中Linux是其中之一:-)

类型

man popen
Run Code Online (Sandbox Code Playgroud)

在终端中阅读更多相关信息.

编辑

是否popen生成单向或双向管道取决于实现.在LinuxOpenBSD中,popen生成单向管道,它们是只读管道或只写管道.在OS X上,FreeBSDNetBSD popen生成双向管道.


Ste*_*ker 9

我曾经为别人写了一些示例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);
}
Run Code Online (Sandbox Code Playgroud)


Jor*_*ira 7

  1. 创建两个管道pipe(...),一个用于stdin,一个用于stdout.
  2. fork(...) 这个过程.
  3. 在子进程(fork(...)返回0的dup (...)那个)中,管道为stdin/ stdout.
  4. exec[v][e] 要在子进程中启动programm文件.
  5. 在父进程(一个其中fork)返回子的PID)做一个循环,从孩子的读取stdout(select(...)poll(...),read(...))到缓冲区,直到子终止(waitpid(...)).
  6. stdin如果期望的话,最终为孩子提供输入.
  7. close(...)管道完成后.


Jon*_*ler 5

对于简单的单向通信, popen() 是一个不错的解决方案。但是,它不适用于双向通信。

IMO,imjorge (Jorge Ferreira) 给出了双向通信的大部分答案(80%?) - 但省略了一些关键细节。

  1. 父进程关闭用于向子进程发送消息的管道的读取端至关重要。
  2. 至关重要的是,子进程关闭用于向子进程发送消息的管道的写端。
  3. 父进程关闭用于向父进程发送消息的管道的写端至关重要。
  4. 至关重要的是,子进程关闭用于向父进程发送消息的管道的读取端。

如果您不关闭管道未使用的末端,那么当其中一个程序终止时,您将无法获得合理的行为;例如,子进程可能正在从其标准输入中读取,但除非管道的写入端在子进程中关闭,否则它永远不会获得 EOF(读取零字节),因为它仍然打开管道并且系统认为它有时可能会开始写入该管道,即使它当前挂起等待从中读取某些内容。

写入过程应考虑是否处理在没有读取过程的管道上写入时给出的 SIGPIPE 信号。

您必须了解管道容量(取决于平台,可能只有 4KB)并设计程序以避免死锁。