写vs fprintf - 为什么不同,哪个更好?

时间:2013-02-26 00:13:41

标签: c pthreads printf

我最近根据POSIX 1003.1c开始学习pthreads的奇迹。

PThreads可能看起来很复杂,但它们基本上是我们在类中用来创建并行行为的简单线程:https://computing.llnl.gov/tutorials/pthreads/

在我还在学习的时候,老师给了我们一个C代码来玩具:

/* Creates two threads, one printing 10000 "a"s, the other printing
   10000 "b"s.
   Illustrates: thread creation, thread joining. */

#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include "pthread.h"

void * process(void * arg)
{
  int i;
  fprintf(stderr, "Starting process %s\n", (char *) arg);
  for (i = 0; i < 100; i++) {
       write(1, (char *) arg, 1);
//      fprintf(stdout, (char *) arg, 1);
  }
  return NULL;
}

int main()
{
  int retcode;
  pthread_t th_a, th_b;
  void * retval;

  retcode = pthread_create(&th_a, NULL, process, "a");
  if (retcode != 0) fprintf(stderr, "create a failed %d\n", retcode);

  retcode = pthread_create(&th_b, NULL, process, "b");
  if (retcode != 0) fprintf(stderr, "create b failed %d\n", retcode);

  retcode = pthread_join(th_a, &retval);
  if (retcode != 0) fprintf(stderr, "join a failed %d\n", retcode);

  retcode = pthread_join(th_b, &retval);
  if (retcode != 0) fprintf(stderr, "join b failed %d\n", retcode);

  return 0;
}
    运行和编译的指令(对于linux):  
  • 运行命令:`sudo apt-get install build-essential`
  •  
  • 下载此代码(显然是xD)
  •  
  • 使用以下命令进行编译:`gcc -D_REENTRANT filenName.c -lpthread`
  •  
  • 使用以下命令运行结果:`。/ a.out`

一切正常但我不明白为什么我的输出顺序会有所不同,具体取决于writefprintf的使用情况。

当我使用write时,我得到一个随机的字母输出,如下所示:

Starting process a
aaaaaaaaaaaaaaaaaaaaaaaaaaaaStarting process b
aaababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

但是当我使用fprintf时,我总是得到类似于:

的输出
Starting process a
Starting process b
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababbabaabaabaababbabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

在这种情况下,文本“Starting process”始终首先出现,并且不与输出的其余部分混合。为什么会这样?是因为write速度非常快而且fprintf速度较慢吗?

作为C程序员,我应该使用哪一个?为什么?

1 个答案:

答案 0 :(得分:12)

write是一个系统调用:它将给定的字符直接发送到操作系统,(理论上,通常在实践中)将它们立即发送到输出设备,如屏幕或磁盘。

fprintf(和fwrite以及任何需要FILE *参数的内容)是一个库调用,它在发送之前缓冲或收集程序中的数据。这使它能够发送更大,更统一的数据块,从而提高效率。

您在write看到的是,每个调用都会导致线程切换,因为程序会等待操作系统确认写入是否成功。当一个线程在等待时,另一个线程会有时间。

fprintf,它从来没有做过如此特殊的事情。它实际上只是一个用a填充数组的线程,直到它完成。在收到填充的缓冲区(通过write)之前,操作系统并不明智。然后,由于第一个线程没有更多的工作,它运行第二个。如果您打印了更多字符,则会看到fprintf还会交错ab,因为这些块会被发送到操作系统。

至于“快”和“慢”,write在发送输出时更直接,但fprintf几乎在其他方面都更快,并且是一般正确的选择(或{{ 1}}更类似于fwrite)。