【问题标题】:how does popen2() work in c?popen2() 如何在 c 中工作?
【发布时间】:2016-02-04 21:18:02
【问题描述】:

我试图在我的程序中使用 pipe、fork 和 dup 执行 md5sume 命令。我找到了成功运行的 sum 代码,但我无法理解某些代码行。这是我的代码:

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;

}

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;

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);

  }

else 

  {

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;

}

我不明白 popen 函数。这条线到底是做什么的?

*infp = p_stdin[WRITE];

管道如何相互通信?

【问题讨论】:

  • 格式化你的代码!删除不必要的空行。
  • 我猜你说的是popen2() 不是popen()。我还猜想第二个代码块是popen2() 函数。您应该参考man 2 pipe 并阅读说明。管道由 2 个文件描述符表示,一个用于写入,一个用于读取。您在其中写入的内容可以从中读取。在fork() 之后,其中一个进程可以写入,另一个从中读取,因此它们可以通信。
  • 是的,我知道这个。我也知道它是 popen2 函数。但我不明白使用整数来实现双向管道,它不是在人中!!
  • READ 和 WRITE 从何而来?

标签: c pipe fork dup2


【解决方案1】:

我不明白 popen 函数。

管道如何相互通信?

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

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

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

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

【讨论】:

  • 我知道这个。我的主要问题是关于双向管道。你知道在 popen 中我们可以在第二个参数处设置 w 或 r 心情,但在我的程序中我需要使用 rw 心情。所以我需要双向管道!
  • 管道是单向的。 popen 仅支持 'r' 或 'w' 并且不支持其他选项,例如 'read and write'。如果需要使用管道进行双向通信,您可能需要实现两个管道,每个方向一个。
猜你喜欢
  • 1970-01-01
  • 2018-11-27
  • 2016-06-13
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2012-02-29
  • 2011-05-02
相关资源
最近更新 更多