Сведения о вопросе

Henry

22:04, 18th August, 2020

Теги

linux   bash   pipe   device    

Bash Обработка Труб

Просмотров: 444   Ответов: 3

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

cat file.txt | tail -20

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

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

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

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


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

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



  Сведения об ответе

PIRLO

18:27, 26th August, 2020

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

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

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

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

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


  Сведения об ответе

SEEYOU

03:45, 29th August, 2020

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


  Сведения об ответе

nYU

13:26, 26th August, 2020

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться