【问题标题】:Linux pipe, fork and execlp: how to get the value written into stream 1Linux pipe、fork 和 execlp:如何获取写入流 1 的值
【发布时间】:2014-05-01 23:53:10
【问题描述】:

我使用函数 (L) 通过execlp() 执行另一个程序 (K)。 在K程序中,将结果写入流1:

write(1, (char *)&o, sizeof(int));

既然execlp()之后,L的剩余部分就不会被执行了,怎么才能得到写在stream 1中的结果呢?

不要问我为什么要这样做。这是一个项目的要求。

我听从了你们的建议,但现在的问题是,K 程序获取参数的方式来自流(一个标准流,另一个流),我正在使用管道将参数写入相应的流(已经完成由父母)。

在子 exec 之后,在父部分,我从流 0 中读取(K 程序将其结果写回流 1)。但我能得到的是父进程写入流的内容,而不是 K 程序写回的内容。 怎么了?我需要添加另一个管道吗?

谢谢!!

【问题讨论】:

  • 你创建了管道;你分叉;孩子整理它的管道(将管道连接到正确的位置并关闭文件描述符)并执行 K;父进程整理其管道(关闭足够多的文件描述符)并从 K 读取响应。
  • 有一本关于 Linux 编程的书。我建议你得到它
  • @staticx:只有一本书?你会建议哪个?也许The Linux Programming Interface Handbook?还是史蒂文斯Advanced Programming in the Unix Environment?或者...
  • staticx 建议 Linux Programming By Example,日期为 1999 年。我还没有读过它。它在亚马逊上得到了很好的评价。我唯一担心的是日期,但基本面没有太大变化。 (LPI 书是 2010 年的;史蒂文斯是 2013 年的。)

标签: c++ c linux fork pipe


【解决方案1】:

Jonathan Leffler 在他的评论中提到的关键见解是,在调用execlp() 之前,您需要fork 正在运行的程序L

在分叉之后,父进程继续执行L 的其余部分,子进程通过调用execlp() 变形为程序K,除非出现错误,否则它永远不会返回。

因此,“L 的剩余部分不会被执行”的断言是不正确的。如果您正确编写函数L,它在父进程中执行。

更新:由于 OP 使他的问题更加具体,我将附加到这个答案。

如果要检索子进程写给stdout(fd 1)的内容,需要在fork之前新建一个管道,并将这个管道的写端复制到子进程的stdout中。

这是一个示例程序,对pipe man page 稍作修改。

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

int
main(int argc, char *argv[])
{
    int pipefd[2];
    pid_t cpid;
    char buf;

    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (cpid == 0) {    /* Child writes into the pipe */
        close(pipefd[0]);          /* Close unused read end */

        // Copy the writing end of the pipe into STDOUT for the child.
        dup2(pipefd[1], STDOUT_FILENO);

        // Execute your program L here, and its stdout will be captured by the pipe.
        const char* message = "Child is speaking to stdout!";
        write(STDOUT_FILENO, message, strlen(message));
        write(STDOUT_FILENO, "\n", 1);


        close(pipefd[1]);
        _exit(EXIT_SUCCESS);

    } else {            /* Parent reads child's stdout  from the pipe */
        close(pipefd[1]);          /* Close unused write end */

        // Here the parent process is reading the child's stdout.
        while (read(pipefd[0], &buf, 1) > 0)
            write(STDOUT_FILENO, &buf, 1);
        wait(NULL);                /* Wait for child */
        exit(EXIT_SUCCESS);
    }
}

【讨论】:

  • 非常感谢!!虽然出现了一个新问题:/该函数工作正常,但我是从 main 调用它。返回 main 后,main 中的 cout 将不再工作。我尝试在调用之前备份 cout,然后在之后恢复它,就像这样(cplusplus.com/reference/ios/ios/rdbuf),但它仍然无法正常工作。 cerr 会工作。非常感谢!
  • @fuiiii,请针对不相关的问题提出新问题。如果此答案解决了您最初的问题,请将其标记为已接受的答案。
猜你喜欢
  • 2018-06-19
  • 1970-01-01
  • 1970-01-01
  • 2016-01-26
  • 1970-01-01
  • 1970-01-01
  • 2013-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多