2008-08-21 1 views
29

Кто-нибудь знает, как баш обрабатывает передачу данных по трубам?Обработка сточных шахт

cat file.txt | tail -20 

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

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

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

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


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

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

ответ

54

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

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

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

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

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

0

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

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

1

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

Смежные вопросы