напишите vs fprintf-почему разные и что лучше?

недавно я начал изучать чудеса pthreads в соответствии с POSIX 1003.1 c.

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 %sn", (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 %dn", retcode);

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

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

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

  return 0;
}
    Инструкции по запуску и компиляции (для linux):
  • Run команда: 'sudo apt-get install build-essential'
  • загрузите этот код (очевидно, xD)
  • для компиляции используйте следующую команду: 'gcc-d_reentrant filenName.c-lpthread'
  • выполнить результат с помощью команды: `./а.из`

все работает, но я не понимаю, почему мой порядок вывода отличается в зависимости от использования write или fprintf.

Когда я использую write Я получаю случайный вывод букв, таких как следующий:

Starting process a
aaaaaaaaaaaaaaaaaaaaaaaaaaaaStarting process b
aaababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

но когда я использую fprintf Я всегда получаю нечто похожее на:

Starting process a
Starting process b
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababbabaabaabaababbabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

в этом случае отображается текст "запуск процесса" всегда появляется первым и не смешивается с остальной частью выходного. Почему это происходит? Это потому что write и fprintf медленнее?

как программист C, какой из них я должен использовать и почему?

2 ответов


write является системным вызовом: он отправляет данные символы непосредственно в операционную систему, которая (в теории, и часто на практике) отправляет их сразу на устройство вывода, такое как экран или диск.

fprintffwrite и все, что принимает FILE * аргумент) - это вызов библиотеки, который буферизует или собирает данные внутри вашей программы перед ее отправкой. Это позволяет ему отправлять большие, более однородные куски данных, что улучшает эффективность.

то, что вы видите с write является то, что каждый вызов вызывает переключатель потока, как программа ждет операционной системы, чтобы подтвердить, удалось ли запись. Когда один поток ждет, другой поток получает время.

С fprintf, Он никогда не делает ничего такого исключительного. На самом деле это всего лишь один поток, заполняющий массив aпока не закончим. Операционная система ничего не знает, пока не получит заполненный буфер (через write). Затем с первый поток больше не работает, он запускает второй. Если вы напечатали больше символов, вы увидите fprintf также interleave aи b'S, как куски отправляют в операционную систему.

Что касается "быстро" и" медленно",write является более непосредственным в отправке его вывода, но fprintf быстрее практически любым другим способом и является общим правильным выбором (или fwrite что больше похоже на write).


Write обертывает вызов ядра, и он не буферизован. Он просто копирует n байтов из буфера в файловый дескриптор.

fprintf буферизуется, а также предназначен для обработки строк и замены различных %d, %s параметрами, поэтому по этой причине гораздо сложнее выполнить анализ строки, которую он получает.