Writing to two file descriptors by only one operation

拜拜、爱过 提交于 2019-12-11 18:34:25

问题


I want to implement logging functionality in C and log messages to both stdout and some file. I would like to write something like fprintf(logout, "msg"); with somehow declared FILE* logout which will redirect strings to both stdout and some file. Is it possible?


回答1:


You apparently want a FILE-like object that redirects its writes to two underlying FILEs (stdout and the log file). Standard C doesn't allow "subclassing" FILE objects in any way, so this is not possible in C. However, GNU libc does, so if your program is Linux-only, you can do that with some programming. As this is extremely non-portable, it is strongly recommended against.

A more portable way to achieve this is by writing to a pipe and creating a process or thread that reads from the pipe and writes to both underlying files. For example, assuming POSIX:

FILE *tee_file(FILE *fp1, FILE *fp2)
{
  int fds[2];
  if (pipe(fds))
    return NULL;
  switch (fork()) {
    case 0: {
      char buf[512];
      int nread;
      FILE *r = fdopen(fds[0], "r");
      close(fds[1]);
      while ((nread = fread(buf, 1, sizeof buf, r)) {
        fwrite(buf, 1, nread, fp1);
        fwrite(buf, 1, nread, fp2);
      }
      _exit(0);
    }
    case -1:
      return NULL;
  }
  close(fds[0]);
  return fdopen(fds[1], "w");
}

/* after calling "fp = tee_file(fp1, fp2)", writes to fp
   end up in fp1 and fp2. */

Both approach add a good deal of complication to your program which should be justified by a very good reason. What you want is to use a logging framework that allows writing to multiple outputs (they all do), or write your own as outlined by H2CO3's answer.




回答2:


If this is on Linux, you can open a pipe to the tee command:

FILE *logout = popen("tee logfile", "w");



回答3:


Why don't you make your very own logging function?

int log_fprintf(FILE *stream, const char *restrict fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    vfprintf(stream, fmt, args);
    va_end(args);

    va_start(args, fmt);
    int n = vfprintf(stdout, fmt, args);
    // conceptually, rather `stderr`, please!
    va_end(args);

    return n;
}


来源:https://stackoverflow.com/questions/15716636/writing-to-two-file-descriptors-by-only-one-operation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!