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