微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我最近根据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,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,"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,"join b Failed %d\n",retcode);

  return 0;
}

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

一切正常但我不明白为什么我的输出顺序根据write或fprintf的使用而有所不同.

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

Starting process a
aaaaaaaaaaaaaaaaaaaaaaaaaaaaStarting process b
aaababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

但是当我使用fprintf时,我总是得到类似于的输出

Starting process a
Starting process b
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababbabaabaabaababbabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

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

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

解决方法

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

fprintf(和fwrite以及任何带有FILE *参数的东西)是一个调用,它在发送之前缓冲或收集程序中的数据.这允许它发送更大,更均匀的数据块,从而提高效率.

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

使用fprintf,它永远不会做任何特别的事情.它实际上只是一个用a填充数组的线程,直到它完成.在收到填充的缓冲区(通过写入)之前,操作系统不是更明智的.然后,因为第一个线程没有更多的工作,它运行第二个.如果您打印了更多字符,您会看到fprintf还会在将块发送到操作系统时交错显示和b.

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

原文地址:https://www.jb51.cc/c/117638.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐