Символы <
, >
, >>
, |
не являются процессами в том же смысле, что и исполняемые файлы, такие как ls
. Скорее, это инструкции для оболочки, которые изменяют способы создания других процессов.
Во-первых, обратите внимание, что, как бы вы ни вводили команды Linux, вы на самом деле напрямую не взаимодействуете с самой операционной системой Linux. Вы используете программу, называемую оболочкой - скорее всего, /bin/bash
, но доступно несколько различных программ оболочки, большинство из которых работают во многом одинаково. Основное назначение оболочки - интерпретировать ваш ввод для запуска других процессов. Это включает системный вызов Linux fork
(или, возможно, clone
) для создания нового процесса в качестве дочернего процесса процесса оболочки, за которым следует системный вызов execve
чтобы этот дочерний процесс загрузился и запустил указанную программу с указанными аргументами.
Оболочка может выполнять различные биты интерпретации на входе, чтобы определить, какой будет действительная программа и аргументы, например, подстановка псевдонимов команд, подстановка переменных среды и расширение символов ~
, *
и []
. Точно так же символы <
, >
, >>
и |
имеют особое значение для оболочки, но вместо того, чтобы изменять имя или аргументы исполняемого файла, они точно изменяют способ создания дочернего процесса.
Процесс Linux обычно начинает свою жизнь с трех открытых «файловых дескрипторов»: стандартный ввод, стандартный вывод и стандартная ошибка. По умолчанию дочерние процессы оболочки будут использовать тот же ввод / вывод / ошибку, что и оболочка, что означает, что они могут получать ввод с клавиатуры через тот же механизм, что и оболочка, и вывод процесса появляется в том же окне. При использовании инструкций перенаправления <
, >
и >>
оболочка изменяет файловые дескрипторы процесса между fork
и execve
, так что даже до запуска исполняемого файла в child, один или несколько его файловых дескрипторов по умолчанию будут фактически читать / записывать в именованные файлы.
Когда используется символ "pipe" |
, оболочка запускает два дочерних процесса примерно в одно и то же время, но с выходом первого процесса, подключенным ко входу второго процесса. Это включает системный вызов pipe
, чтобы создать пару файловых дескрипторов, где запись в один дескриптор просто помещает данные в память операционной системы, пока они не будут считаны из другого дескриптора.
Так, например,
grep 'MAGIC' file1.txt | sort
будет (не обязательно в этом порядке):
- Создать пару дескрипторов файла канала
- Создайте дочерний процесс для команды
grep
.
- Замените стандартный дескриптор выходного файла дочернего элемента, чтобы использовать конец записи канала.
- Начните команду
grep
с помощью execve
.
- Создайте дочерний процесс для команды
sort
.
- Замените стандартный дескриптор входного файла дочернего элемента, чтобы использовать конец чтения канала.
- Начните команду
sort
с помощью execve
.
- Подождите, пока дочерний процесс
sort
завершится.
В терминах «даже если функция конвейера встроена в систему, должен быть найден фрагмент кода», вы найдете код для интерпретации этих специальных символов оболочки в коде для программы оболочки.