Я решил написать чуть более подробное объяснение.
«Волшебство» здесь заключается в операционной системе. Обе программы запускаются примерно в одно и то же время и работают в одно и то же время (операционная система назначает им интервалы времени для запуска процессора), как и любой другой одновременно запущенный процесс на вашем компьютере (включая терминальное приложение и ядро). , Таким образом, перед передачей любых данных процессы выполняют любую необходимую инициализацию. В вашем примере 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. Если вы запустите команду во второй раз, операционная система, скорее всего, сохранит содержимое файла file.txt в кэше, и вы вряд ли увидите заметную задержку (если только файл file.txt не очень большой или файл больше не кэшируется). .)
Большинство операций, выполняемых на вашем компьютере, связаны с вводом-выводом, то есть обычно вы ожидаете получения данных с жесткого диска, сетевого устройства и т. Д.