Я читал о том, как каналы реализованы в ядре Linux, и хотел проверить мое понимание. Если я ошибаюсь, будет выбран ответ с правильным объяснением.
- В Linux есть VFS с именем pipefs, которая монтируется в ядре (а не в пространстве пользователя)
- pipefs имеет один суперблок и монтируется в своем корневом (
pipe:
)/
- pipefs не могут быть просмотрены напрямую в отличие от большинства файловых систем
- Вход в pipefs через
pipe(2)
системный вызов pipe(2)
Системный вызов , используемый оболочками для трубопроводов с|
оператором (вручную или с любого другого процесса) создает новый файл в pipefs , который ведет себя очень похоже на обычный файл- Файл с левой стороны оператора канала
stdout
перенаправляется во временный файл, созданный в pipefs. - Файл в правой части оператора pipe имеет свой
stdin
набор для файла в pipefs - pipefs хранится в памяти, и благодаря некоторой магии ядра не должен быть выгружен
Является ли это объяснение того, как трубы (например ls -la | less
) функционируют в значительной степени правильно?
Одна вещь, которую я не понимаю, это то, как что-то вроде bash будет задавать процесс stdin
или stdout
возвращать дескриптор файла pipe(2)
. Я пока не смог ничего найти по этому поводу.
pipe()
Вызов ядра наряду с техникой , которая поддерживает его (pipefs
и т.д.) значительно ниже уровень , чем|
оператор , предоставляемый в оболочке. Последнее обычно реализуется с использованием первого, но это не обязательно.|
оператор просто вызываетpipe(2)
как процесс, как это делает bash.Ответы:
Ваш анализ до сих пор в целом правильно. Способ, которым оболочка может установить stdin процесса в дескриптор канала, может быть (псевдокод):
источник
dup2
нужен вызов, а вы не можете просто назначить дескриптор канала для stdin?pipe()
.dup2()
Вызова позволяет абоненту скопировать дескриптор файла определенного числового значения (необходимо потому , что 0, 1, 2 STDIN, стандартный вывод, STDERR). Это ядро эквивалентно «назначению непосредственно в stdin». Обратите внимание, что глобальная переменная библиотеки времени выполнения Cstdin
- это aFILE *
, которая не связана с ядром (хотя она инициализирована для подключения к дескриптору 0).dup2
звонок не меняетсяp[1]
. Вместо этого он делает две ручкиp[1]
и0
указывает на один и тот же объект ядра (канал). Поскольку дочерний процесс не нуждается в двух дескрипторах stdin (и вp[1]
любом случае не знает, что это за номерный дескриптор ),p[1]
он закрывается раньшеexec
.