dup2、stdout 和 stderr 出现问题

发布于 2024-09-28 08:26:23 字数 837 浏览 9 评论 0原文

当该程序运行时,“stderr”行显示在“stdout”行之前。为什么?我认为 dup2 会让 stderr 和 stdout 使用相同的文件描述符,因此缓冲应该没有问题。我在 Solaris 10 上使用 gcc 3.4.6。

#include <errno.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
    int fd[2];
    int pid;
    char buf[256];
    int n;

    if(pipe(fd) < 0) {
        perror("pipe");
        return 1;
    }
    if((pid = fork()) < 0) {
        perror("fork");
        return 1;
    }
    else if(pid > 0) { // parent
        close(fd[1]);
        if((n = read(fd[0], buf, sizeof(buf))) > 0) {
            buf[n] = 0;
            printf("%s", buf);
        }
    }
    else {
        dup2(fd[1], fileno(stdout));
        dup2(fd[1], fileno(stderr));
        close(fd[1]);
        fprintf(stdout,"stdout\n");
        fprintf(stderr,"stderr\n");
    }
    return 0;
}

When this program is run, the "stderr" line is displayed before the "stdout" line. Why? I thought dup2 would make stderr and stdout use the same file descriptor so there should be no problem with buffering. I'm using gcc 3.4.6 on Solaris 10.

#include <errno.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
    int fd[2];
    int pid;
    char buf[256];
    int n;

    if(pipe(fd) < 0) {
        perror("pipe");
        return 1;
    }
    if((pid = fork()) < 0) {
        perror("fork");
        return 1;
    }
    else if(pid > 0) { // parent
        close(fd[1]);
        if((n = read(fd[0], buf, sizeof(buf))) > 0) {
            buf[n] = 0;
            printf("%s", buf);
        }
    }
    else {
        dup2(fd[1], fileno(stdout));
        dup2(fd[1], fileno(stderr));
        close(fd[1]);
        fprintf(stdout,"stdout\n");
        fprintf(stderr,"stderr\n");
    }
    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

对不⑦ 2024-10-05 08:26:23

FILE * 的 stdout 和 stderr 以及文件描述符 1 和 2 之间存在差异。在本例中,是 FILE 导致了您不期望的行为。默认情况下,stderr 不会进行缓冲,因此在发生错误时,您可以以最可靠的方式打印出消息,即使这种打印的性能会降低程序的整体性能。

stdout 默认情况下是缓冲的。这意味着它有一个内存数组,用于存储您告诉它写入的数据。它会等待,直到数组(称为缓冲区)填充到一定水平或(如果它设置为行缓冲,通常是这样)直到它看到 '\n'。不过,您可以调用 fflush(stdout); 来使其继续并打印。

您可以更改FILE *的缓冲设置。 man 3 setbuf 具有为您执行此操作的函数。

在您的示例中,stdout 缓冲区在将“stderr”写入屏幕时保存字符串“stdout”。然后退出程序后,所有打开的 FILE * 都会被刷新,因此“stdout”会被打印出来。

There is a difference between the FILE *s stdout and stderr and the file descriptors 1 and 2. In this case it is the FILEs that are causing the behavior that you weren't expecting. stderr is not buffered by default so that in the case of an error you can print out the message in the most reliable manner, even though the performance of this printing slows down overall performance of the program.

stdout, by default, is buffered. This means that it has an array of memory that it is storing the data that you told it to write in. It waits until it has the array (called a buffer) filled to a certain level or (if it is setup for line buffering, which it often is) until it sees a '\n'. You could call fflush(stdout); to make it go ahead and print, though.

You can change the buffering settings of FILE *. man 3 setbuf has the functions that do this for you.

In your example the stdout buffer was holding the string "stdout" while the "stderr" was being written to the screen. Then upon exiting the program all of the open FILE * are flushed, so "stdout" then got printed.

海之角 2024-10-05 08:26:23

两个流 stdout 和 stderr 可能使用相同的文件描述符,但在 FILE 流将任何数据写入其底层文件描述符之前,数据将存储在流的缓冲区中。 stdout 和 stderr 中的缓冲区不会仅仅因为两个流连接到相同的文件描述符而变得相同。

请注意,此缓冲是由 stdio 库中的 FILE 流完成的,而不是由操作系统内核及其文件描述符完成的。那里可能还有其他缓冲,但这个问题是由上面的 stdio 库级别引起的。

The two streams stdout and stderr may be using the same file descriptor, but before a FILE stream writes any data to its underlying file descriptor, the data is stored in the stream's buffer. The buffers in stdout and stderr don't become the same just because the two streams are connected to the same file descriptor.

Note that this buffering is done by the FILE streams in the stdio library, not by the OS kernel and its file descriptors. There may be other buffering going on there too, but this problem is caused by the stdio library level above.

£噩梦荏苒 2024-10-05 08:26:23

刷新标准输出怎么样?

dup2(fd[1], fileno(stdout));
dup2(fd[1], fileno(stderr));
close(fd[1]);
fprintf(stdout,"stdout\n");
fflush(stdout);
fprintf(stderr,"stderr\n");

(刚刚尝试过并且有效)

What about flushing stdout?

dup2(fd[1], fileno(stdout));
dup2(fd[1], fileno(stderr));
close(fd[1]);
fprintf(stdout,"stdout\n");
fflush(stdout);
fprintf(stderr,"stderr\n");

(just tried and it works)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文