Каковы правила автоматической промывки буфера stdout в C?
Мне просто интересно, какие условия должны быть удовлетворены, чтобы автоматически очистить буфер stdout.
прежде всего, я был смущен тем, что этот псевдо-код не печатает вывод каждой итерации:
while (1) {
printf("Any text");
sleep(1);
}
но если я добавлю символ новой строки, он будет.
после нескольких экспериментов я обнаружил, что на моей машине сброшен буфер stdout:
- когда я ставлю в stdout 1025 символов или более;
- когда я читаю стандартный ввод;
- когда я ставлю символ новой строки в stdout;
первое условие полностью ясно - когда буфер заполнен, он должен быть сброшен. Второй тоже разумный. Но почему персонаж newline вызывает покраснение? Каковы другие имплицитные условия для этого?
5 ответов
правила автоматической промывки буфера stdout -реализация-определено (ID). Это ID, когда поток unbuffered, полностью буферизованной или линия буферизованный.
когда поток unbuffered символы предназначены, чтобы появиться из источника или в месте назначения как можно скорее. В противном случае символы могут накапливаться и передаваться в среду хоста или из нее в виде блока.
когда поток полностью буферизованной, символы предназначены для передачи В или из среды хоста в виде блока при заполнении буфера.
когда поток линия буферизованный, символы предназначены для передачи В или из среды хоста в виде блока при обнаружении символа новой строки. Кроме того, символы предназначены для передачи в виде блока в среду хоста при заполнении буфера, когда ввод запрашивается в небуферизованном потоке или когда ввод запрашивается в буферизованном потоке строки, который требует передачи символов из среды хоста.
поддержка этих характеристик определяется реализацией, ... C11dr §7.21.3 3
Мне просто интересно, какие условия должны быть удовлетворены, чтобы автоматически очистить буфер stdout.
если код хочет обеспечить вывод конечно покраснел, используйте fflush()
. Другие условия, которые могут автоматически сбросить поток, определены реализацией.
посмотреть man-страница для setbuf(3)
. По умолчанию stdout
установлен в режим буферизации линии.
printf()
и его варианты работают с буферизованным выходом и делегируют write()
. Таким образом, эта буферизация управляется реализацией библиотеки C printf
, с настройками буфера и буфера, расположенными в FILE
структура.
также стоит отметить разницу между разделом 3 и разделом 2 man-страниц unix. Раздел 2 состоит вызовов функций, которые напрямую разговаривают с операционной системой и делают то, что в противном случае было бы невозможно сделать из чистой пользовательской программы. Раздел 3 состоит из вызовов функций, которые пользователь может воспроизвести самостоятельно, которые часто делегируются вызовам раздела 2. Функции раздела 2 содержат низкоуровневую "магию", которая позволяет программам C взаимодействовать с внешним миром и выполнять функции ввода-вывода. функции раздела 3 могут обеспечить более удобный интерфейс для раздела 2 функции.
printf
, scanf
, getchar
, fputs
и другие FILE *
функции все функции раздела 3, которые делегируют write()
и read()
, которые являются функциями раздела 2. read()
и write()
не буфер. printf()
взаимодействует с буфером в FILE
структура, и иногда решает отправить содержимое буфера через write()
.
выходной поток, который буферизуется линией, должен быть сброшен всякий раз, когда выводится новая строка.
реализация может (но не требуется) очистить все выходные потоки с буферизацией строк всякий раз, когда выполняется попытка чтения из любого входного потока с буферизацией строк.
реализациям не разрешается делать потоки полностью буферизованными по умолчанию, если не установлено, что они не связаны с "интерактивным устройством". Так когда? stdin / stdout-это терминалы, которые не могут быть полностью буферизованы, только линейно буферизованы (или не буферизованы).
Если вам нужна только промывка, когда выход на терминал, достаточно предположить, что запись новой строки приводит к промывке. В противном случае вы должны явно вызвать fflush
везде, где вам нужно промыть.
существует много обстоятельств, когда буферизованный вывод в потоке сбрасывается автоматически:
- когда вы пытаетесь сделать вывод и выходной буфер полон.
- когда поток закрывается.
- когда программа завершает работу, вызывая exit.
- при записи новой строки, если поток буферизован по строке.
- всякий раз, когда операция ввода на любой поток читает данные из файла.
stdout
is line буферизация по умолчанию.
Если вы хотите сбросить буферизованный вывод в другое время, вы можете вызвать fflush.
7.21.3 файлы
...
3 Когда поток unbuffered, символы должны появляться из источника или на назначения как можно скорее. В противном случае символы могут накапливаться и передается в среду хоста или из нее в виде блока. Когда поток полностью буферизованной, символы предназначены для передачи в среду хоста или из нее в виде блока когда буфер заполняется. когда поток линия буферизованный, символы должны быть передается в среду хоста или из нее в виде блока, когда символ новой строки встречающийся. Кроме того, символы предназначены для передачи в виде блока на хост среда при заполнении буфера, при запросе ввода в небуферизованный поток или когда входной сигнал спрошен на буферизованном линией потоке который требует передачи символы с хоста среды. Поддержка этих характеристик реализация-определена и может быть затронута черезsetbuf
иsetvbuf
функции.
...
7 при запуске программы три текстовых потока предопределены и не должны быть открыты явно - стандартный ввод (для чтения обычных входных), стандартный вывод (для написания обычный выход), и Стандартная ошибка (для записи диагностического вывода). Как изначально открыл, стандартный поток ошибок не полностью буферизован;стандартный ввод и стандартный выходные потоки полностью буферизуются тогда и только тогда, когда поток можно определить, чтобы не ссылаться к интерактивному устройству.
таким образом, поток с буферизацией строки будет сброшен на новую строку. На большинстве систем у меня есть опыт работы с,stdout
строка буферизуется в интерактивном сеансе.