2

这只是一个更大程序的一小部分,但我试图从 execvp 获取输出,我已经正确设置了 execvp dup2,并将其引导到管道中。当涉及到使用 read 读取管道的全长时,我的问题就出现了,我不知道execvp每次的输出有多大,因为它可能因输入而异。

    int fd[2];
    pipe(fd);
    pid_t pid = fork();
    if (pid == 0) {
        close(fd[0]);
        dup2(fd[1], 1);
        execvp(msg.v,(char *[]){msg.v,NULL});
    } else if (pid > 0) {
        close(fd[1]);
        read(fd[0],msg.v,....);
    }

我尝试了几种不同的读取大小,但要么不够,要么最后我得到随机垃圾空白其他方式去获得输出。

整个程序是服务器的一部分的更多无用信息。我正在制作服务器和客户端..启动服务器给客户端一个终端命令,它通过 INET 流将其发送到服务器,并将输出发送回客户端以显示所有没有 stdio 的输出。

4

2 回答 2

1

您必须注意有多少数据read返回到缓冲区。在read返回正数时,您有更多数据。当程序完成后,它会关闭它的结尾pipe,你read会返回0

} else if (pid > 0) {
    close(fd[1]);
    ssize_t r = read(fd[0],buf,bufsz);
    if (r > 0) do {
        /* ... do something with r bytes in buf */
        r = read(fd[0],buf,bufsz);
    } while (r > 0);
    if (r < 0) {
        perror("read");
        /*...*/
    }
}

如果您看到read出现“系统调用中断”错误,那么您遇到了EINTRcaf 提到的情况。在这种情况下,您read再次重新启动。

        for (;;) {
            r = read(fd[0],buf,bufsz);
            if (r != -1 || errno != EINTR) break;
        }

我假设您没有进行非阻塞 I/O,因此您不会遇到“资源暂时不可用”消息。

于 2012-08-07T01:36:25.610 回答
1

您继续阅读,直到read()返回0,这表示 EOF(或 -1errno设置为永久错误,即EAGAINor以外的任何内容EINTR)。

你不能忽略它的返回值read()- 它告诉你它返回了多少字节。这就是为什么您在缓冲区末尾看到“垃圾”的原因 - 在这些情况下read()并没有填满整个缓冲区,并且您忽略了返回值,因此您不知道它实际返回了多少。

于 2012-08-07T01:37:52.010 回答