增加标准输出缓冲区大小。

3
我正在运行一个程序,它启动了一个进程,然后该进程会将内容写入stdout,我的程序会调用这个stdout。问题是,我需要的输出大约有42000字节。看起来stdout缓冲区大小为8192,我不想让它在达到42000之前就进行flush。请问有没有设置的方法?
我尝试了以下代码:
setvbuf ( stdout , NULL , _IOFBF , 50000 ); // ie set it to 50000 bytes

我在子进程的代码上工作,但它似乎根本不起作用。有人有什么想法吗?


请注意,必须在第一次写入缓冲区之前调用 setvbuf();之后,setvbuf() 调用将不起作用。 - Jonathan Leffler
@JonathanLeffler:不,之后它的行为是未定义的。它可能会破坏您的文件或使整个程序(或计算机)崩溃。 - R.. GitHub STOP HELPING ICE
3个回答

6
您需要为setvbuf()提供一个缓冲区才能正常工作。
static char buf[50000]; /* buf must survive until stdout is closed */
setvbuf ( stdout , buf , _IOFBF , sizeof(buf) );

根据手册

int setvbuf(FILE *stream, char *buf, int mode , size_t size);
...
除了无缓冲文件,buf参数应该指向至少大小为size字节的缓冲区;此缓冲区将代替当前缓冲区。如果参数buf为NULL,则仅受影响的是模式;新缓冲区将在下一次读或写操作时分配。

这里有一个示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[]) {
    char msg[42000];
    char buf[50000];

    setvbuf(stdout, buf, _IOFBF, sizeof(buf));
    memset(msg, 'a', sizeof(msg));
    msg[sizeof(msg)-1] = '\0';
    puts(msg);
    exit(0);
}

在我的系统上,strace 输出显示只有一次写入 42000 字节。

似乎这个没起作用。返回的数据仍然是8192。也许是父进程的标准输入的问题。 - user1276273
在调用 setvbuf() 之前,您是否执行了其他的 I/O 操作? - jxh
是的,我有一个标准输入,即:fgets(parameters, 2000, stdin); - user1276273
@user1276273:stdin没问题,但如果在尝试对其进行setvbuf()之前在stdout上进行了I/O操作,则无法正常工作。请参考更新的答案,并使用strace ./a.out > /dev/null在您的系统上尝试示例程序。您是否看到一个42000字节的单个write() - jxh
抱歉jxh - 实际上是node.js出了一些问题。我使用node.js启动一个进程,该进程是c程序。由于某种原因,我认为问题在于stdout缓冲区。但实际上不是这样的。node.js接收其子进程数据的方式存在一些奇怪的行为。 - user1276273
请注意,如果此程序从main返回而不是调用exit,则会产生未定义的行为,因为当数组的生命周期结束时,缓冲区仍在使用中。 - R.. GitHub STOP HELPING ICE

2
作为对 jxh 答案的补充信息:
char buf[50000];
setvbuf ( stdout , buf , _IOFBF , sizeof(buf) );
/*close stdout before the programs finishes or even before buf goes out of scope*/
fclose(stdout);

你还需要关闭stdout,因为man setvbuff也提到:

你必须确保buf指向的空间在流关闭时仍然存在,这也会在程序终止时发生。


这其实可以作为对我的回答的评论,但还是点赞了。 - jxh
调用 exit 而不是从 main 返回,确保在程序退出之前 buf 的生命周期不会结束。 - R.. GitHub STOP HELPING ICE

0

查看ulimit的手册,或者这样做太天真了吗?因为我很确定操作系统将用户FIFO限制为8k。

希望您不需要一个新内核!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接