需要澄清 C 中的 popen2()

问题描述 投票:0回答:1

我正在尝试使用

md5sum
pipe
fork
在程序中执行
dup
命令。我发现一些代码运行成功,但我不明白其中几行代码。

代码:

int main()
{
  int infp, outfp;
  char buf[128];

  if (popen2("md5sum", &infp, &outfp) <= 0)
  {
    printf("Unable to exec sort\n");
    exit(1);
  }

  write(infp, "hello\n", 2);
  close(infp);

  *buf = '\0';
  read(outfp, buf, 128);
  printf("buf = '%s'\n", buf);

  return 0;
}
#define READ 0
#define WRITE 1

pid_t popen2(const char *command, int *infp, int *outfp)
{
  int p_stdin[2], p_stdout[2];
  pid_t pid;

  if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0)
    return -1;

  pid = fork();

  if (pid < 0)
      return pid;
  else if (pid == 0)
  {
    close(p_stdin[WRITE]);
    dup2(p_stdin[READ], READ);
    close(p_stdout[READ]);
    dup2(p_stdout[WRITE], WRITE);

    execl("/bin/sh", "sh", "-c", command, NULL);
    perror("execl");
    exit(1);
  }

  if (infp == NULL)
    close(p_stdin[WRITE]);
  else
    *infp = p_stdin[WRITE];

  if (outfp == NULL)
    close(p_stdout[READ]);
  else
    *outfp = p_stdout[READ];

  return pid;
}

popen2
示例来自 https://stackoverflow.com/a/548148/4072736

我不明白

popen2
示例的结尾。这些线到底有什么作用?

*infp = p_stdin[WRITE];

*outfp = p_stdout[READ];

管道之间如何通信?

c pipe fork popen dup2
1个回答
2
投票

我不明白popen函数。

管道之间如何通信?

pipe() : 管道是单向的,是内核中的字节流缓冲区。由于它是字节流类型,写入者可以写入任意数量的字节,读取者可以读出任意数量的字节。但是,请注意,顺序读取是可能的,但查找(如 lseek)是不可能的。由于管道是单向的,写入管道的数据将在内核中缓冲,直到从管道的读取端读取。另外,如果管道已满,写入就会阻塞。

假设 fd 是一个由 2 个文件描述符 (int fd[2]) 组成的整数数组,那么 pipeline(fd) 系统调用应创建一个管道并返回一对文件描述符,使得 fd[1] (stdout 为 1) ) 应为管道的写入端,而 fd[0](stdin 为 0)应为管道的读取端。与命名管道(如 FIFO - 文件系统中具有名称的管道)不同,匿名管道只能在相关进程(如父子进程)之间使用。因此,应进行fork以在子进程中复制这2个父文件描述符,从而父进程与子进程共享管道,以便子进程应在写端写入,父进程应从管道的读端读取,或者父进程应写入写端end 和 child 应从管道的 read-end 读取。应注意确保父级或子级根据场景关闭未使用的读取(fd[0])文件描述符/未使用的写入(fd[1])文件描述符。

popen() :popen 使您能够将另一个程序作为新进程调用,从而向其传输数据或从中接收数据。如果是 popen,请注意数据流的方向基于第二个参数。我们不需要手动创建子进程,因为 popen 会自动 forks 创建子进程,启动 shell 并执行通过 popen 传递的命令参数。它还根据类型参数自动在父级和子级之间建立适当的读取或写入流。

因此,popen() 简化了事情,因为它避免了手动调用/调用 pipeline、fork、exec 的需要,并简化了根据参数类型自动在父/子之间建立适当的流。然而,popen 的另一面是,应该注意的是,每次调用 popen() 都会导致创建额外的进程 - 也就是说,除了正在调用的程序之外,每次都会调用 shell -转向导致高资源消耗。

© www.soinside.com 2019 - 2024. All rights reserved.