LINUX.ORG.RU

История изменений

Исправление firkax, (текущая версия) :

Касательно stdout/stderr и их мнимой «синхронизации» отдельный коммент.

Действительно, если бездумно чередовать fprintf в stdout и stderr, то надписи могут (не во всех случаях) появиться на экране не в том порядке, как вызывались соответствующие fprintf. Ситуация может усугубиться либо выводом неполных строк, либо конвеером (типа | grep xxx да даже просто | cat) на выходе программы. Создаётся впечатление, будто что-то там синхронизировалось обычно, а тут вот синхронизация нарушилась. Обманчивое.

На самом деле, тут всё дело в буферизации вывода, и делает её вовсе не терминал и не ядро, а сама программа, кодом внутри функций printf и других из stdio.h. А именно (по умолчанию, но это поведение можно перенастроить в коде программы), всё что пишется в stderr - сразу попадает в fd 2 через syscall write(), а вот то, что пишется в stdout - попадает в fd 1 далеко не сразу. Если fd 1 - терминал, то оно попадает обычно при выводе очередного перевода строки. Если fd 1 - не терминал (а например конвеер в grep), то оно попадает ещё позже - при заполнении внутреннего юзерспейсного буфера в структуре FILE). А вот дальше, обычно, fd 1 и fd 2 - синонимы, и write(1,...) с write(2,...) делают одно и то же, никакой рассинхронизации между ними быть не может. Если там есть конвеер, то уже не синонимы, да, fd1 идёт в конвеери и что с ним будет дальше - зависит исключительно от конвеерной проги (grep?), fd2 (если его специально не редиректить) остаётся терминалом.

Но шелл тут, во всех случаях, ни при чём, и влиять не ситуацию не должен!

Ещё отмечу, что всё вышеописанное полностью детерминировано, и даже если stderr c stdout и выводятся не в том порядке, то это не какая-то рандомная «рассихронизацияя», а полностью заранее известное поведение (с точностью до каждого символа), опять повторюсь, независимо от шеллов.

Исходная версия firkax, :

Касательно stdout/stderr и их мнимой «синхронизации» отдельный коммент.

Действительно, если бездумно чередовать fprintf в stdout и stderr, то надписи могут (не во всех случаях) появиться на экране не в том порядке, как вызывались соответствующие fprintf. Ситуация может усугубиться либо выводом неполных строк, либо конвеером (типа | grep xxx да даже просто | cat) на выходе программы. Создаётся впечатление, будто что-то там синхронизировалось обычно, а тут вот синхронизация нарушилась. Обманчивое.

На самом деле, тут всё дело в буферизации вывода, и делает её вовсе не терминал и не ядро, а сама программа, кодом внутри функций printf и других из stdio.h. А именно (по умолчанию, но это поведение можно перенастроить в коде программы), всё что пишется в stderr - сразу попадает в fd 2 через syscall write(), а вот то, что пишется в stdout - попадает в fd 1 далеко не сразу. Если fd 1 - терминал, то оно попадает обычно при выводе очередного перевода строки. Если fd 1 - не терминал (а например конвеер в grep), то оно попадает ещё позже - при заполнении внутреннего юзерспейсного буфера в структуре FILE). А вот дальше, обычно, fd 1 и fd 2 - синонимы, и write(1,...) с write(2,...) делают одно и то же, никакой рассинхронизации между ними быть не может. Если там есть конвеер, то уже не синонимы, да, fd1 идёт в конвеери и что с ним будет дальше - зависит исключительно от конвеерной проги (grep?), fd2 (если его специально не редиректить) остаётся терминалом. Но шелл тут, во всех случаях, ни при чём!