Подтвердить что ты не робот

Как работает труба в Linux?

Как работает трубопровод? Если я запустил программу через CLI и перенаправил вывод в файл, я смогу передать этот файл в другую программу по мере ее написания?

В основном, когда одна строка записывается в файл, я хотел бы, чтобы она была немедленно передана в мое второе приложение (я пытаюсь динамически рисовать график из существующей программы). Просто не уверен, завершает ли первая строка команду, прежде чем перейти к следующей команде.

Любая обратная связь будет принята с благодарностью!

4b9b3361

Ответ 1

Если вы хотите перенаправить вывод одной программы на вход другого, просто используйте простой конвейер:

program1 arg arg | program2 arg arg

Если вы хотите сохранить вывод program1 в файл и передать его в program2, вы можете использовать tee(1)

program1 arg arg | tee output-file | program2 arg arg

Все программы в конвейере запускаются одновременно. Большинство программ обычно используют блокировку ввода-вывода: если при попытке прочитать их ввод и ничего не существует, они блокируют: то есть они останавливаются, а операционная система отменяет их, пока они не станут доступными (чтобы избежать питания процессор). Аналогично, если ранее программа в конвейере записывает данные быстрее, чем более поздняя программа может ее прочитать, в конечном итоге буфер канала заполняется, а блок записи блокируется: ОС отменяет его до тех пор, пока буфер буфера не будет очищен читателем, а затем он может продолжить писать снова.


ИЗМЕНИТЬ

Если вы хотите использовать вывод program1 в качестве параметров командной строки, вы можете использовать backquotes или синтаксис $():

# Runs "program1 arg", and uses the output as the command-line arguments for
# program2
program2 `program1 arg`

# Same as above
program2 $(program1 arg)

Синтаксис $() должен быть предпочтительным, поскольку они более четкие, и они могут быть вложенными.

Ответ 2

Трубопровод не выполняет первую команду перед запуском второй. Unix (и Linux) объединяет все команды одновременно. Команда будет приостановлена, если

  • Он голоден для ввода.

  • Он произвел значительно больше результатов, чем его преемник готов к употреблению.

Для большинства программ вывод буферизуется, что означает, что ОС накапливает значительный объем вывода (возможно, 8000 символов или около того), прежде чем передавать его на следующий этап конвейера. Эта буферизация используется, чтобы избежать слишком большого переключения между процессами и ядром.

Если вы хотите сразу же отправить вывод на конвейер, вы можете использовать небуферизованный ввод-вывод, который в C означает вызов чего-то типа fflush(), чтобы быть уверенным, что любой буферный вывод немедленно отправляется на следующий процесс. Небуферизованный вход также возможен, но обычно не нужен, потому что процесс, который голодает для ввода, обычно не ждет полного буфера, но будет обрабатывать любой вход, который вы можете получить.

Для типичных приложений небуферизованный выход не рекомендуется; вы обычно получаете максимальную производительность по умолчанию. В вашем случае, однако, когда вы хотите сделать динамическое графическое отображение сразу, первый процесс имеет доступную информацию, вы определенно хотите использовать небуферизованный вывод. Если вы используете C, вызов fflush(stdout), когда вы хотите, чтобы отправленный результат был достаточным.

Ответ 3

Если ваши программы обмениваются сообщениями с помощью stdin и stdout, убедитесь, что вы либо вызываете fflush(stdout) после записи, либо можете найти способ отключить стандартную буферизацию ввода-вывода. Лучшая ссылка, о которой я могу думать, действительно описывает, как лучше всего реализовать конвейеры в C/С++, Расширенное программирование в среде UNIX или Сетевое программирование UNIX: Том 2. Возможно, вы могли бы начать с в этой статье.

Ответ 4

Если ваши две программы настаивают на чтении и записи файлов и не используют stdin/stdout, вы можете обнаружить, что вместо файла можно использовать named pipe.

Создайте именованный канал с помощью команды mknod (1):

$ mknod /tmp/named-pipe p

Затем настройте свои программы для чтения и записи в /tmp/named -pipe (используйте любой путь/имя, которое, по вашему мнению, подходит).

В этом случае обе программы будут работать параллельно, блокируя при необходимости, когда труба станет полной/пустой, как описано в других ответах.