Вопрос

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

cat file.txt | tail -20

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

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

Заранее благодарю вас за ваши ответы!

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


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

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

Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

cat просто распечатает данные в standard out, которые будут перенаправлены в standard in of tail.Это можно увидеть на странице руководства bash.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top