stringtranslate.com

Конвейер (Unix)

Конвейер из трех программных процессов, выполняемых на текстовом терминале

В Unix-подобных компьютерных операционных системах конвейер — это механизм межпроцессного взаимодействия с использованием передачи сообщений. Конвейер — это набор процессов , связанных вместе своими стандартными потоками , так что выходной текст каждого процесса ( stdout ) передается непосредственно в качестве входных данных ( stdin ) следующему. Второй процесс запускается, поскольку первый процесс все еще выполняется, и они выполняются одновременно . Концепция конвейеров была поддержана Дугласом Макилроем в Bell Labs , прародине Unix , во время разработки Unix, формируя философию ее набора инструментов . [1] [2] Назван по аналогии с физическим конвейером . Ключевой особенностью этих конвейеров является «скрытие внутренних компонентов» (Ritchie & Thompson, 1974). Это, в свою очередь, обеспечивает большую ясность и простоту системы.

Эта статья посвящена анонимным каналам , где данные, записанные одним процессом, буферизуются операционной системой до тех пор, пока они не будут прочитаны следующим процессом, и этот однонаправленный канал исчезает после завершения процессов. Это отличается от именованных каналов , где сообщения передаются в канал или из канала, которому присвоено имя, путем создания файла, и остаются после завершения процессов. Стандартный синтаксис оболочки для анонимных каналов заключается в перечислении нескольких команд, разделенных вертикальными чертами («каналы» в обычном словоблудии Unix):

команда1 | команда2 | команда3    

Например, чтобы просмотреть файлы в текущем каталоге ( ls ), сохранить только строки вывода ls , содержащие строку «ключ» ( grep ), и просмотреть результат на прокручиваемой странице ( less ), пользователь вводит следующее в поле командная строка терминала:

лс  | ключ grep | меньше     

Команда ls -lвыполняется как процесс, выходные данные (stdout) которого передаются по конвейеру на вход (stdin) процесса для grep key; и то же самое для процесса для less. Каждый процесс принимает входные данные от предыдущего процесса и создает выходные данные для следующего процесса через стандартные потоки . Каждый из них |сообщает оболочке о необходимости соединить стандартный вывод команды слева со стандартным вводом команды справа с помощью механизма межпроцессного взаимодействия, называемого (анонимным) каналом , реализованного в операционной системе. Трубы однонаправленные; данные проходят по конвейеру слева направо.

Пример

Ниже приведен пример конвейера, реализующего своего рода проверку орфографии для веб- ресурса, указанного URL-адресом . Ниже приводится объяснение того, что он делает.

локон "https://en.wikipedia.org/wiki/Pipeline_(Unix)/Pipeline_(Unix)" |  sed 's/[^a-zA-Z ]/ /g' |  tr 'AZ ' 'az\n' |   grep '[az]' |  сортировка  | comm  -23  -  < ( сортировка  /usr/share/dict/words ) | меньше
  1. curlполучает HTML- содержимое веб-страницы (может использоваться wgetв некоторых системах).
  2. sedзаменяет все символы (из содержимого веб-страницы), не являющиеся пробелами или буквами, на пробелы. ( Новые строки сохраняются.)
  3. trменяет все прописные буквы на строчные и преобразует пробелы в строках текста в символы новой строки (каждое «слово» теперь находится на отдельной строке).
  4. grepвключает только строки, содержащие хотя бы один строчный буквенный символ (все пустые строки удаляются).
  5. sortсортирует список «слов» в алфавитном порядке, а переключатель -uудаляет дубликаты.
  6. commнаходит общие строки между двумя файлами, -23подавляет строки, уникальные для второго файла, а также строки, общие для обоих, оставляя только те, которые встречаются только в первом указанном файле. Вместо -имени файла commиспользуется его стандартный ввод (в данном случае из конвейера). sort /usr/share/dict/wordsсортирует содержимое файла wordsв алфавитном порядке, как и commожидалось, и <( ... )выводит результаты во временный файл (через подстановку процесса ), который commчитает. Результатом является список слов (строк), которых нет в /usr/share/dict/words.
  7. lessпозволяет пользователю пролистывать результаты.

Конвейеры в интерфейсах командной строки

Все широко используемые оболочки Unix имеют специальную синтаксическую конструкцию для создания конвейеров. При любом использовании команды записываются последовательно, разделенные символом вертикальной черты ASCII (который по этой причине часто называют «символом вертикальной черты»). Оболочка запускает процессы и организует необходимые соединения между их стандартными потоками (включая некоторый объем буферной памяти). |

Поток ошибок

По умолчанию стандартные потоки ошибокstderr ») процессов в конвейере не передаются через канал; вместо этого они объединяются и направляются на консоль . Однако многие оболочки имеют дополнительный синтаксис для изменения этого поведения. Например, в оболочке csh|& использование вместо |означает, что стандартный поток ошибок также следует объединить со стандартным выводом и передать следующему процессу. Оболочка Bash также может объединять стандартные ошибки с |&версией 4.0 [3] или с помощью 2>&1, а также перенаправлять их в другой файл.

Трубный завод

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

Однако оболочка может выполнять обработку напрямую, используя так называемую мельницу или конвейерную мельницу (поскольку whileкоманда используется для «фрезерования» результатов исходной команды). Обычно эта конструкция выглядит примерно так:

команда | при чтении -r var1 var2 ... ; do # обработать каждую строку, используя переменные, разобранные на var1, var2 и т.д. # (обратите внимание, что это может быть подоболочка: var1, var2 и т.д. будут недоступны # после завершения цикла while; некоторые оболочки, такие как zsh и более новые # версии оболочки Korn, обработайте команды слева от оператора # в подоболочке) готово              

Такая конвейерная мельница может работать не так, как предполагалось, если тело цикла включает команды, такие как catи ssh, которые считываются из stdin: [4] на первой итерации цикла такая программа (назовем ее стоком ) прочитает оставшийся вывод из command, и цикл затем завершится (результаты зависят от особенностей стока). Есть несколько возможных способов избежать такого поведения. Во-первых, некоторые стоки поддерживают возможность отключения чтения из stdin(например, из ssh -n). В качестве альтернативы, если стоку не нужно считывать какие-либо входные данные, stdinчтобы сделать что-то полезное, его можно передать < /dev/nullв качестве входных данных.

Поскольку все компоненты канала выполняются параллельно, оболочка обычно создает подпроцесс (подоболочку) для обработки его содержимого, что делает невозможным распространение изменений переменных во внешнюю среду оболочки. Чтобы решить эту проблему, «pipemill» вместо этого может быть загружен из документа here , содержащего команду replace , которая ожидает завершения работы конвейера, прежде чем перерабатывать содержимое. В качестве альтернативы для параллельного выполнения можно использовать именованный канал или подстановку процесса . В GNU bash также есть lastpipeвозможность отключить разветвление для последнего компонента канала. [5]

Программное создание конвейеров

Конвейеры могут создаваться под управлением программы. pipe() Системный вызов Unix просит операционную систему создать новый объект анонимного канала . В результате в процессе появляются два новых открытых файловых дескриптора: конец канала, доступный только для чтения, и конец канала, доступный только для записи. Концы канала кажутся обычными анонимными файловыми дескрипторами , за исключением того, что у них нет возможности поиска.

Чтобы избежать тупиковой ситуации и использования параллелизма, процесс Unix с одним или несколькими новыми каналами обычно вызывает fork()создание новых процессов. Затем каждый процесс закроет конец(а) канала, который он не будет использовать, перед созданием или потреблением каких-либо данных. Альтернативно, процесс может создавать новые потоки и использовать канал для связи между ними.

Именованные каналы также могут быть созданы с помощьюmkfifo()или ,mknod()а затем представлены в качестве входного или выходного файла программам по мере их вызова. Они позволяют создавать многопутевые каналы и особенно эффективны в сочетании со стандартным перенаправлением ошибок или сtee.

Выполнение

В большинстве Unix-подобных систем все процессы конвейера запускаются одновременно, их потоки соответствующим образом связаны и управляются планировщиком вместе со всеми другими процессами, выполняемыми на машине. Важным аспектом этого, отличающим каналы Unix от других реализаций каналов, является концепция буферизации : например, передающая программа может выдавать 5000 байт в секунду , а принимающая программа может принимать только 100 байт в секунду, но не данные потеряны. Вместо этого выходные данные отправляющей программы сохраняются в буфере. Когда принимающая программа готова прочитать данные, следующая программа в конвейере считывает данные из буфера. Если буфер заполнен, программа-отправитель останавливается (блокируется) до тех пор, пока получатель не удалит из буфера хотя бы часть данных. В Linux размер буфера составляет 65 536 байт (64 КБ). Доступен сторонний фильтр с открытым исходным кодом под названием bfr, который при необходимости обеспечивает буферы большего размера.

Сетевые трубы

Такие инструменты, как netcat и socat, могут подключать каналы к сокетам TCP/IP .

История

Концепция конвейера была изобретена Дугласом Макилроем [6] и впервые описана на страницах руководства Unix версии 3 . [7] [8] Макилрой заметил, что большую часть времени командные оболочки передавали выходной файл одной программы в качестве входных данных для другой.

Его идеи были реализованы в 1973 году, когда («за одну лихорадочную ночь», как писал Макилрой) Кен Томпсон добавил pipe()системные вызовы и каналы в оболочку и несколько утилит в версию 3 Unix. «На следующий день, — продолжал Макилрой, — мы увидели незабываемую оргию острот, когда все присоединились к восторгу от сантехнических работ». Макилрой также благодарит Томпсона за эту |нотацию, которая значительно упростила описание синтаксиса каналов в версии 4 . [9] [7]

Несмотря на то, что каналы Unix были разработаны независимо, они связаны с «коммуникационными файлами», разработанными Кеном Лохнером [10] в 1960-х годах для Дартмутской системы разделения времени, и им предшествовали . [11]

В коммуникативных последовательных процессах (CSP) Тони Хоара каналы Макилроя получили дальнейшее развитие. [12]

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

Другие операционные системы

Эта функция Unix была заимствована другими операционными системами, такими как MS-DOS и пакетом CMS Pipelines на VM/CMS и MVS , и в конечном итоге стала называться шаблоном проектирования каналов и фильтров разработки программного обеспечения .

Смотрите также

Рекомендации

  1. ^ Махони, Майкл С. «Проект устной истории Unix: Release.0, Начало». Макилрой: Это было одно из немногих мест, где я практически осуществлял управленческий контроль над Unix, давил на эти вещи, да.
  2. ^ "Пророческие петроглифы". cm.bell-labs.com . Архивировано из оригинала 8 мая 1999 года . Проверено 22 мая 2022 г.
  3. ^ "Примечания к выпуску Bash" . tiswww.case.edu . Проверено 14 июня 2017 г.
  4. ^ «Взаимодействие цикла оболочки с SSH» . 6 марта 2012 г. Архивировано из оригинала 6 марта 2012 г.
  5. ^ Джон1024. «Как сохранить результаты команды «найти» в виде массива в Bash». Переполнение стека .{{cite web}}: CS1 maint: числовые имена: список авторов ( ссылка )
  6. ^ «Создание операционной системы UNIX». Лаборатории Белла. Архивировано из оригинала 14 сентября 2004 года.
  7. ^ Аб Макилрой, доктор медицины (1987). Читатель Research Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Лаборатории Белла. 139.
  8. ^ Томпсон К. , Ричи Д.М. (февраль 1973 г.). Руководство программиста UNIX, третье издание (PDF) (технический отчет) (3-е изд.). Лаборатории Белла. п. 178.
  9. ^ «Трубы: Краткое введение» . Информационный проект Linux. 23 августа 2006 г. [Создано 29 апреля 2004 г.] . Проверено 7 января 2024 г.
  10. ^ "Разделение времени в Дартмуте" (DOC) . Рочестерский технологический институт . Проверено 7 января 2024 г.
  11. ^ «Данные». cm.bell-labs.com . Архивировано из оригинала 20 февраля 1999 года . Проверено 22 мая 2022 г.
  12. ^ Кокс, Расс. «Лаборатории Bell и потоки CSP». Распределительный щит . Проверено 7 января 2024 г.

Внешние ссылки