напишите 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
является системным вызовом: он отправляет данные символы непосредственно в операционную систему, которая (в теории, и часто на практике) отправляет их сразу на устройство вывода, такое как экран или диск.
fprintf
(и fwrite
и все, что принимает FILE *
аргумент) - это вызов библиотеки, который буферизует или собирает данные внутри вашей программы перед ее отправкой. Это позволяет ему отправлять большие, более однородные куски данных, что улучшает эффективность.
то, что вы видите с write
является то, что каждый вызов вызывает переключатель потока, как программа ждет операционной системы, чтобы подтвердить, удалось ли запись. Когда один поток ждет, другой поток получает время.
С fprintf
, Он никогда не делает ничего такого исключительного. На самом деле это всего лишь один поток, заполняющий массив a
пока не закончим. Операционная система ничего не знает, пока не получит заполненный буфер (через write
). Затем с первый поток больше не работает, он запускает второй. Если вы напечатали больше символов, вы увидите fprintf
также interleave a
и b
'S, как куски отправляют в операционную систему.
Что касается "быстро" и" медленно",write
является более непосредственным в отправке его вывода, но fprintf
быстрее практически любым другим способом и является общим правильным выбором (или fwrite
что больше похоже на write
).
Write обертывает вызов ядра, и он не буферизован. Он просто копирует n байтов из буфера в файловый дескриптор.
fprintf буферизуется, а также предназначен для обработки строк и замены различных %d, %s параметрами, поэтому по этой причине гораздо сложнее выполнить анализ строки, которую он получает.