当前位置:首页> 正文

关于linux:从C程序中执行程序

关于linux:从C程序中执行程序

Execute program from within a C program

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

我不确定这是否是标准的C函数。我需要在Linux下可以使用的解决方案。


您要使用popen。它为您提供了一个单向管道,您可以使用该管道访问程序的stdin和stdout。

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

类型

1
man popen

在终端上阅读有关它的更多信息。

编辑

popen是产生单向管道还是双向管道取决于实现。在Linux和OpenBSD中,popen产生单向管道,这些管道是只读或只写的。在OS X上,FreeBSD和NetBSD popen产生双向管道。


我为其他人写了一些示例C代码,展示了如何做到这一点。这是给你的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

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

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\
"
, 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);
}

  • pipe(...)创建两个管道,一个用于stdin,一个用于stdout
  • fork(...)该过程。
  • 在子进程(fork(...)返回0的子进程)中,dup (...)将管道传送到stdin / stdout
  • exec[v][e]子进程中要启动的程序文件。
  • 在父进程(其中fork返回子PID的进程)中,执行一个循环,将子stdout(select(...)poll(...)read(...))从子中读取到缓冲区中,直到
    子项终止(waitpid(...))。
  • 最终如果希望孩子在stdin上为其提供输入。
  • 完成close(...)管道后。

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

    国际海事组织(IMO),伊莫赫(Imjorge)(Jorge Ferreira)给出了双向通信的大部分答案(80%?),但省略了一些关键细节。

  • 至关重要的是,父进程必须关闭用于向子进程发送消息的管道的读取端。
  • 子进程关闭用于向子进程发送消息的管道的写端至关重要。
  • 父进程必须关闭用于向父进程发送消息的管道的写端,这一点至关重要。
  • 子进程关闭用于向父进程发送消息的管道的读取端至关重要。
  • 如果不关闭管道的未使用端,则当其中一个程序终止时,您将不会表现出明智的行为。例如,子级可能正在从其标准输入中进行读取,但是除非在子级中关闭管道的写端,否则它将永远不会得到EOF(读取的零字节),因为它仍然具有打开的管道并且系统认为即使某个管道当前处于挂起状态,正在等待从该管道读取某些内容,有时仍可能会写该管道。

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

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


    您可以使用系统调用,阅读system(3)的联机帮助页。


    我认为您可以使用

    freopen

    为此。


    展开全文阅读

    相关内容