Обработка трубы

Кто-нибудь знает, как bash обрабатывает отправку данных по каналам?

cat file.txt | tail -20

Эта команда печатает все содержимое файла file.txt в буфер, который затем читается хвостом? Или эта команда, скажем, печатает содержимое файла file.txt построчно, а затем делает паузу в каждой строке для обработки хвоста, а затем запрашивает дополнительные данные?

Причина, по которой я спрашиваю, состоит в том, что я пишу программу на встроенном устройстве, которое в основном выполняет последовательность операций над некоторым фрагментом данных, где выходные данные одной операции отправляются как входные данные следующей операции. Я хотел бы знать, как linux (bash) справляется с этим, поэтому, пожалуйста, дайте мне общий ответ, а не конкретно, что происходит, когда я запускаю "cat file.txt | tail -20".

РЕДАКТИРОВАТЬ: Shog9 указал на соответствующую статью в Википедии, это не привело меня непосредственно к этой статье, но помогло мне найти это: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation, которая действительно имела Информация, которую я искал.


Я извиняюсь за то, что не прояснил себя. Конечно, вы используете канал и, конечно, вы используете stdin и stdout соответствующих частей команды. Я предполагал, что это было слишком очевидно, чтобы утверждать

Я спрашиваю, как это обрабатывается / реализуется. Поскольку обе программы не могут работать одновременно, как данные передаются со стандартного ввода в стандартный вывод? Что произойдет, если первая программа генерирует данные значительно быстрее, чем вторая программа? Выполняет ли система первую команду до тех пор, пока она либо не будет прервана, либо ее буфер stdout не заполнится, а затем перейдет к следующей программе и т. Д. В цикле, пока не останется больше данных для обработки или пока не появится более сложный механизм ?

21.08.2008 00:20:34
3 ОТВЕТА
РЕШЕНИЕ

Я решил написать чуть более подробное объяснение.

«Волшебство» здесь заключается в операционной системе. Обе программы запускаются примерно в одно и то же время и работают в одно и то же время (операционная система назначает им интервалы времени для запуска процессора), как и любой другой одновременно запущенный процесс на вашем компьютере (включая терминальное приложение и ядро). , Таким образом, перед передачей данных процессы выполняют любую необходимую инициализацию. В вашем примере tail анализирует аргумент '-20', а cat анализирует аргумент 'file.txt' и открывает файл. В какой-то момент хвост достигает точки, где ему требуется ввод, и он сообщает операционной системе, что ожидает ввода. В какой-то другой момент (до или после, это не имеет значения) cat начнет передавать данные в операционную систему, используя стандартный вывод. Это входит в буфер в операционной системе. В следующий раз, когда tail получает временной интервал на процессоре после того, как cat поместил в буфер некоторые данные, он получит некоторое количество этих данных (или всех), которые покидают буфер в операционной системе. Когда буфер пуст, в какой-то момент tail придется ждать, пока cat выдаст больше данных. Если cat выводит данные намного быстрее, чем tail обрабатывает их, буфер расширяется. В конечном итоге cat завершит вывод данных, но tail все равно будет обрабатывать, поэтому cat закроется, а tail обработает все оставшиеся данные в буфере. Операционная система будет сигнализировать хвост, когда их больше нет входящих данных с EOF. Хвост обработает оставшиеся данные. В этом случае tail, вероятно, просто получает все данные в кольцевой буфер из 20 строк, и когда операционная система сигнализирует о том, что поступающих данных больше нет, она сбрасывает последние двадцать строк в свой собственный стандартный вывод, который просто отображается в терминале. Поскольку tail - намного более простая программа, чем cat, она, скорее всего, будет проводить большую часть времени в ожидании, когда cat поместит данные в буфер.

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

Если вдаваться в подробности, если вы откроете какой-нибудь монитор процессов (специфичный для операционной системы), например «top» в Linux, вы увидите полный список запущенных процессов, большинство из которых эффективно используют 0% процессора. Большинство приложений, если они не обрабатывают данные, проводят большую часть своего времени, ничего не делая. Это хорошо, поскольку позволяет другим процессам иметь беспрепятственный доступ к процессору в соответствии с их потребностями. Это достигается в основном тремя способами. Процесс может перейти к инструкции режима сна (n), где он в основном говорит ядру подождать n миллисекунд, прежде чем дать ему еще один временной интервал для работы. Чаще всего программе нужно ждать чего-то от другой программы, например, «хвост», ожидая, пока больше данных не попадет в буфер. В этом случае операционная система активизирует процесс, когда будет доступно больше данных. Наконец, ядро ​​может выгружать процесс в середине выполнения, предоставляя некоторые процессорные интервалы другим процессам. 'cat' и 'tail' - простые программы. В этом примере tail тратит большую часть своего времени в ожидании большего количества данных в буфере, а cat тратит большую часть своего времени в ожидании, пока операционная система извлекает данные из жесткого диска. Узким местом является скорость (или медлительность) физического носителя, на котором хранится файл. Эта ощутимая задержка, которую вы можете обнаружить при первом запуске этой команды, - это время, которое требуется считывающим головкам на дисководе для поиска позиции на жестком диске, где находится file.txt. Если вы запустите команду во второй раз,

Большинство операций, которые вы выполняете на своем компьютере, связаны с вводом-выводом, то есть вы обычно ожидаете получения данных с жесткого диска, сетевого устройства и т. Д.

55
21.08.2008 05:46:23
Это неверно означает, что выходной буфер из catбудет расти бесконечно; но ОС также может блокировать запись, когда выходной буфер достигает своего максимального размера.
tripleee 22.12.2019 11:03:10

cat просто распечатает данные в стандартный формат, который будет перенаправлен к стандартному параметру. Это можно увидеть на странице руководства bash.

Другими словами, паузы не происходит, tail просто читает из стандартного входа, а cat просто пишет из стандартного.

0
21.08.2008 00:29:00

Shog9 уже ссылался на статью в Википедии, но в разделе реализации есть нужные детали. Базовая реализация представляет собой ограниченный буфер.

1
21.08.2008 01:45:20