LINUX.ORG.RU

буферизация stdio


0

0

Опять про буферизацию в простом С, но с новой стороны. Понятно, что потоковый вывод (printf) буферизируется. Понятно про setbuf. Но почему он не буферезируется если программа выводит на терминал и буферезируется если выводиться, например, в файл или pipe?

Сейчас объясню проблему. Есть программа, она работает себе и печатает потихоньку всякую диагностику через printf. На терминал всё выводиться, всё устраивает. Может вывод и буферезируется построчно, но это не заметно и вполне приемлемо.

Совсем другая ситуация если поток направляется в файл или pipe. Тут наблюдается буферизация блоками (выяснился и размер блока - 256 байт).

Почему мне это не нравиться. Чтобы удалённо мониторить, что происходит с программой её вывод направляется на ввод другой программулки которая позволят всем заинтересованным лицам эту диагностику просматривать. И тут получаются нехилые задержки, что напрягает. В исходную программу вмешиваться нельзя. поэтому setbuf не придлагать, но имеется возможность изменить способ её запуска, в частности в родительском процессе (который запускает основную программу) поднастроить дескрипторы 0, 1, 2.

Поэтому вопрос. По какому принципу printf изменяет своё поведение в плане буферизации в зависимости от того куда выводит в pipe или терминал? То есть printf проверяет, что дескриптор 1 - это дескриптор именно терминала, или при наследовании дескриптора 1 есть некие настройки дескриптора, указывающие printf поведение при буферизации? Я это к тому, что: могу ли я перед exec основной программы в родительском процессе изменить флаги/режимы дескриптора 1 (который будет указывать на pipe), чтобы printf в основной (дочерней) программе принял построчную буферизацию или работал без неё вообще?


Прозреваю istty(). Попробуй сделать псевдо-терминал.

Absurd ★★★
()

printf("DEBUG: a=%d\n", a);
fflush(stdout);

arsi ★★★★★
()

Из The GNU C Library Reference Manual. Обрати внимание на параметр MODE.

 -- Function: int setvbuf (FILE *STREAM, char *BUF, int MODE, size_t
          SIZE)
     This function is used to specify that the stream STREAM should
     have the buffering mode MODE, which can be either `_IOFBF' (for
     full buffering), `_IOLBF' (for line buffering), or `_IONBF' (for
     unbuffered input/output).

     If you specify a null pointer as the BUF argument, then `setvbuf'
     allocates a buffer itself using `malloc'.  This buffer will be
     freed when you close the stream.

     Otherwise, BUF should be a character array that can hold at least
     SIZE characters.  You should not free the space for this array as
     long as the stream remains open and this array remains its buffer.
     You should usually either allocate it statically, or `malloc'
     (*note Unconstrained Allocation::) the buffer.  Using an automatic
     array is not a good idea unless you close the file before exiting
     the block that declares the array.

     While the array remains a stream buffer, the stream I/O functions
     will use the buffer for their internal purposes.  You shouldn't
     try to access the values in the array directly while the stream is
     using it for buffering.

     The `setvbuf' function returns zero on success, or a nonzero value
     if the value of MODE is not valid or if the request could not be
     honored.

Begemoth ★★★★★
()

>То есть printf проверяет, что дескриптор 1 - это дескриптор именно терминала

Если я правильно помню, что при запуске программы, ещё до выполнения функции main(), glibc инициализирует буферизацию потоков. То есть проверка не в printf, а раньше и проверка простая --- tty или не tty. Поэтому, ИМХО, только запуск через псевдотерминал.

mky ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.