Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 调用popen后如何在父进程和子进程之间使用管道?_C_Pipe_Parent Child_Ipc_Interprocess - Fatal编程技术网

C 调用popen后如何在父进程和子进程之间使用管道?

C 调用popen后如何在父进程和子进程之间使用管道?,c,pipe,parent-child,ipc,interprocess,C,Pipe,Parent Child,Ipc,Interprocess,我希望与子进程通信,如下所示: int main(int argc, char *argv[]) { int bak, temp; int fd[2]; if (pipe(fd) < 0) { // pipe error exit(1); } close(fd[0]); dup2(STDOUT_FILENO, fd[1]); fflush(stdout); bak = dup(1);

我希望与子进程通信,如下所示:

int main(int argc, char *argv[])
{
    int bak, temp;
    int fd[2];
    if (pipe(fd) < 0)
    {
        // pipe error
        exit(1);
    }
    close(fd[0]);
    dup2(STDOUT_FILENO, fd[1]);
    fflush(stdout);
    bak = dup(1);
    temp = open("/dev/null", O_WRONLY);
    dup2(temp, 1);
    close(temp  );
    Mat frame;
    std::vector<uchar> buf;
    namedWindow( "Camera", WINDOW_AUTOSIZE );
    VideoCapture cam(0 + CAP_V4L);
    sleep(1);
    if (!cam.isOpened())
    {
        cout << "\nCould not open reference " << 0 << endl;
        return -1;
    }
    for (int i=0; i<30; i++)
    {
        cam>>frame;
    }
    //cout<<"\nCamera initialized\n";
    /*Set the normal STDOUT back*/
    fflush(stdout);
    dup2(bak, 1);
    close(bak);

    imencode(".png",frame, buf);
    cout<<buf.size()<<endl;
    ssize_t written= 0;
    size_t s = 128;
    while (written<buf.size())
    {
     written += write(fd[1], buf.size()+written, s);

    }
    cout<<'\0';
    return 0;

}
程序正在运行,即sendto的接收器将接收数据

我尝试像在子进程中那样使用管道:

    int fd[2];
    if (pipe(fd) < 0)
    {
        // pipe error
        exit(1);
    }
    close(fd[1]);
    dup2(STDIN_FILENO, fd[0]);
    if ((fp = popen("path/to/exec", "r")) != NULL)
    {
        while((read(fd[0], buf, BUFLEN) > 0)
        {
            sendto(sockfd, buf, strlen(buf),0, addr, alen);
        }
    }
但与此不发送

那么,在这种情况下,如何使用管道来实现与第一种情况相同的行为呢?我是否应该执行dup2STDIN_FILENO,fd[0];或者dup2STDOUT_FILENO,fd[0]


我使用的是sandards,因为文件描述符是由子进程继承的,所以不需要任何其他工作。这就是为什么我认为我可以使用管道,但事实是这样吗?

手动设置管道的常用方法是,父进程可以从中读取子进程的标准输出,其一般步骤如下:

父对象通过调用管道来创建管道 母叉 父对象:其管道写入端的副本 子级通过dup2将管道的写入端复制到其标准输出上 child关闭管道写入端的原始文件描述符 可选子对象:其管道读取端的副本 child执行所需的命令,或者直接执行所需的工作 然后,父对象可以从管道的读取端读取子对象的输出

popen函数可以为您完成所有这些,并将父级的管道端点包装到一个文件中。当然,如果调用者要求相反的方向,它可以也将设置一个管道

您需要理解并理解,在上述程序方案中,重要的是哪些操作由哪个流程执行,以及与同一流程中的其他操作相关的顺序。特别是,在启动子管道之前,父管道不能关闭管道的写入端,因为这样会使管道变得无用。子对象继承一端封闭的管道,通过该管道无法传输任何数据

关于后一个示例,还要注意,将标准输入重定向到管道的读取端不是父级或子级处理的一部分。事实上,你的管道是半封闭的,因此无论如何都无法从中读取任何内容,这只是锦上添花。此外,父级以这种方式重击自己的标准输入。这并不一定是错的,但父母甚至都不依赖它

然而,总的来说,有一个更大的图景你似乎并不欣赏。即使您在父级中执行了您似乎想要的重定向,以便子级可以继承它,popen也会执行它自己的重定向到它自己创建的管道。它返回的文件*是您可以读取子对象输出的方法。您以前可能执行的输出重定向与子级标准输出的澄清无关

原则上,可以使用类似于您的方法来创建另一个方向的第二个重定向,但在这一点上,popen的便利性因素完全丧失了。如果要重定向子级的输入和输出,最好一直使用directpipe/fork/dup2/exec路由

将所有这些应用到第一个示例中,您必须了解,尽管流程可以重定向其自己的标准流,但它不能以这种方式建立到其父流程的管道。父级需要提供管道,否则它不知道该管道。当一个进程将一个文件描述符复制到另一个文件描述符上时,会用新的替换原始文件,如果原始文件已打开,则会关闭它。它不会重新定义原始的。当然,在这种情况下,如果管道的任意一端不再在任何地方打开,管道也就没有用了。

在父管道中:

if (pipe(fd) < 0)
{
    // pipe error
    exit(1);
}
close(fd[0]);
你得到一根管子,然后立即关闭它的一端。这条管道现在毫无用处,因为没有人能够恢复封闭端,因此没有数据可以通过它。您已将管道转换为一端密封的空心圆柱体

然后在孩子身上:

if (pipe(fd) < 0)
{
    // pipe error
    exit(1);
}
close(fd[1]);
创建另一个不相关的管道,并在另一端密封该管道。这两条管道没有连接,现在有两个单独的空心自行车,每一个都在一端密封。任何东西都不能通过它们


如果把东西放在第一个圆筒里,让它出现在另一个圆筒里,那将是一个相当好的魔术。如果不耍花招或巧妙地安排镜像,解决方案是创建一个管道,保持两端打开,并将数据推送到其中。

我不明白您在这里想要实现什么。popen的要点是允许您避免直接管理管道和文件描述符。如果您想要更大的灵活性或不同的界面,那么您可以始终以通常的方式手动执行管道管理和fork/exec。但是把两者混合起来对你有什么好处呢?是的,我知道,我在问题中也说过波本是有效的,但我想了解为什么管道的另一种方式不起作用。这就是我想要达到的目标。顺便说一句,还有很多
这里的代码与管道问题毫无关系,除了看到两个管道的问题外,我真的不知道您想要实现什么。您的两个孩子的样本也使用popen,这有点让人困惑,我不知道您所说的“未发送”的具体含义。什么没有被发送,在哪里,你是怎么说的,你期望被发送什么?为什么是否决票?所以基本上,如果我理解正确,子进程中的fd是错误的。那么我应该传递哪个文件描述符来写呢?你是说在第一个代码中,@FrancescoBoi?在这种情况下,如果父级通过popen启动子级,就像在第二个代码中一样,那么子级只会写入其标准输出。它根本不需要知道重定向。这就是重定向的全部要点,尤其是popen执行的重定向。如果它依赖于子进程做一些特殊的事情,那么它的用处就会小得多。在exec之后做一些特殊的事情,也就是说。那么当我在子进程中写入时,我应该使用什么?您只能写入fd[1]并从fd[0]读取。父对象具有两端,子对象继承两端。这取决于你选择如何使用它们。我真的不知道您想要在父进程和子进程之间交流什么,也不知道您想要实现什么,因此我无法就如何实现它向您提供建议。NB。显示了一个在类似情况下使用socketpair的简单示例-这将允许双向消息,但编写的代码与管道的工作方式相同。另一个疑问是,您说这些管道是不相关的,但我复制了这些管道中的标准输出,因此我以某种方式使它们相关:不是这样吗?我不否认它们可能完全无用,因为此时我可以直接写入std输出。你调用管道两次,就会得到两个不同的管道。说他们有亲戚关系是因为你把一个的一端复制到了stdout上,另一个的另一端复制到了stdin上,就像说两个人有亲戚关系是因为他们坐在同一辆车上。
if (pipe(fd) < 0)
{
    // pipe error
    exit(1);
}
close(fd[1]);