10

私は最近、POSIX1003.1cに従ってpthreadの素晴らしさを学び始めました。

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`

writeすべてが機能しますが、またはの使用によって出力順序が異なる理由がわかりませんfprintf

使用するwriteと、次のような文字がランダムに出力されます。

Starting process a
aaaaaaaaaaaaaaaaaaaaaaaaaaaaStarting process b
aaababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

しかし、私が使用するfprintfと、常に次のような出力が得られます。

Starting process a
Starting process b
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababbabaabaabaababbabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

この場合、「Starting process」というテキストが常に最初に表示され、残りの出力と混合されることはありません。なぜこうなった?writeとても速くてfprintf遅いからですか?

Cプログラマーとして、どちらを使用する必要があり、その理由は何ですか?

4

2 に答える 2

17

writeシステムコールです。指定された文字をオペレーティングシステムに直接送信します。オペレーティングシステムは、(理論的には、多くの場合、実際には)画面やディスクなどの出力デバイスにすぐに送信します。

fprintf(および引数fwriteを取るものはすべてFILE *)ライブラリ呼び出しであり、プログラムを送信する前に、プログラム内のデータをバッファリングまたは収集します。これにより、より大きく、より均一なデータのチャンクを送信できるようになり、効率が向上します。

writeプログラムがオペレーティングシステムが書き込みに成功したかどうかを確認するのを待つ間、各呼び出しによってスレッドスイッチが発生することがわかります。一方のスレッドが待機しているとき、もう一方のスレッドは時間を取得します。

を使用fprintfすると、これほど例外的なことはできません。実際には、a完了するまで配列を'sで埋めるスレッドは1つだけです。オペレーティングシステムは、(を介して)いっぱいになったバッファを受け取るまでは賢明ではありませんwrite。次に、最初のスレッドにはそれ以上の作業がないため、2番目のスレッドが実行されます。より多くの文字を印刷すると、チャンクがオペレーティングシステムに送信されるときに、fprintfインターリーブa'と'も表示されます。b

「速い」と「遅い」に関してwriteは、出力の送信fprintfがより迅速になりますが、他のほとんどすべての点で高速であり、一般的に正しい選択です(またはfwriteに似ていwriteます)。

于 2013-02-26T00:17:58.383 に答える
3

書き込みはカーネル呼び出しをラップし、バッファリングされません。バッファからファイル記述子にnバイトをコピーするだけです。

fprintfはバッファリングされており、文字列処理を実行し、さまざまな%d、%sをパラメータに置き換えることを目的としているため、受信した文字列を解析する必要があるため、実行がはるかに複雑になります。

于 2013-02-26T00:21:38.240 に答える