如何缓冲内存中的stdout并从专用线程写入

Nic*_*ckB 22 c stdout file buffering

我有一个包含许多工作线程的C应用程序.至关重要的是,这些不会阻塞工作线程需要写入磁盘上的文件,我让它们写入内存中的循环缓冲区,然后有一个专用线程将该缓冲区写入磁盘.

工作线程不再阻塞.专用线程可以在写入磁盘时安全地阻塞,而不会影响工作线程(写入磁盘时它不会保持锁定).我的内存缓冲区调整得足够大,以至于编写器线程可以跟上.

一切都很好.我的问题是,我如何为stdout实现类似的东西?

我可以宏printf()写入内存缓冲区,但我无法控制可能写入stdout的所有代码(其中一些代码在第三方库中).

思考?NickB

Nat*_*ohl 34

我喜欢使用的想法freopen.您也可以stdout使用dupdup2重定向到管道,然后使用read从管道中获取数据.

像这样的东西:

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

#define MAX_LEN 40

int main( int argc, char *argv[] ) {
  char buffer[MAX_LEN+1] = {0};
  int out_pipe[2];
  int saved_stdout;

  saved_stdout = dup(STDOUT_FILENO);  /* save stdout for display later */

  if( pipe(out_pipe) != 0 ) {          /* make a pipe */
    exit(1);
  }

  dup2(out_pipe[1], STDOUT_FILENO);   /* redirect stdout to the pipe */
  close(out_pipe[1]);

  /* anything sent to printf should now go down the pipe */
  printf("ceci n'est pas une pipe");
  fflush(stdout);

  read(out_pipe[0], buffer, MAX_LEN); /* read from pipe into buffer */

  dup2(saved_stdout, STDOUT_FILENO);  /* reconnect stdout for testing */
  printf("read: %s\n", buffer);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 当我尝试这样的方法时,如果管道中没有任何东西,我发现`read`会挂起.但是添加`long flags = fcntl(out_pipe [0],F_GETFL); flags | = O_NONBLOCK; fcntl(out_pipe [0],F_SETFL,flags);`到init部分修复了那个问题. (4认同)

dia*_*pir 9

如果您正在使用GNU libc,则可以使用内存流.

  • 我认为这是真正的正确答案。管道方法涉及昂贵的系统调用,并且肯定会阻塞。 (2认同)
  • 该链接已过期,请使用此链接 https://www.gnu.org/software/libc/manual/html_node/String-Streams.html。 (2认同)