stringtranslate.com

Конвейер (Unix)

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

В операционных системах Unix-подобных компьютеров конвейер — это механизм межпроцессного взаимодействия с использованием передачи сообщений. Конвейер — это набор процессов, связанных вместе их стандартными потоками , так что выходной текст каждого процесса ( stdout ) передается непосредственно в качестве ввода ( stdin ) следующему. Второй процесс запускается, пока первый процесс все еще выполняется, и они выполняются одновременно .

Концепция конвейеров была выдвинута Дугласом Макилроем в прародине Unix Bell Labs во время разработки Unix, сформировав его инструментальную философию . Она названа по аналогии с физическим конвейером . Ключевой особенностью этих конвейеров является их «сокрытие внутренностей». Это, в свою очередь, обеспечивает большую ясность и простоту в системе.

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

История

Концепция конвейера была изобретена Дугласом Макилроем [1] и впервые описана в man-страницах версии 3 Unix . [2] [3] Макилрой заметил, что большую часть времени командные оболочки передавали выходной файл из одной программы в качестве входного в другую. Концепция конвейеров была выдвинута Дугласом Макилроем в прародине Unix Bell Labs во время разработки Unix, формируя его философию инструментария . [4] [5]

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

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

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

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

Дальнейшая разработка концепции

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

Выполнение

Механизм конвейера используется для межпроцессного взаимодействия с использованием передачи сообщений. Конвейер — это набор процессов, связанных вместе их стандартными потоками , так что выходной текст каждого процесса ( stdout ) передается непосредственно в качестве ввода ( stdin ) следующему. Второй процесс запускается, когда первый процесс все еще выполняется, и они выполняются одновременно . Он назван по аналогии с физическим конвейером . Ключевой особенностью этих конвейеров является их «сокрытие внутренностей». [10] Это, в свою очередь, обеспечивает большую ясность и простоту в системе.

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

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

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

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

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

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

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

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

ls  -l | grep key | меньше     

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

Пример

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

curl "https://en.wikipedia.org/wiki/Pipeline_(Unix)/Pipeline_(Unix)" |  sed 's/[^a-zA-Z ]/ /g' |  тр 'AZ ' 'az\n' |   grep '[az]' |  сортировка  -u | комм  -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позволяет пользователю пролистывать результаты.

Поток ошибок

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

Трубопроводная мельница

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

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

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

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

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


Создание конвейеров программным способом

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

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

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

Массовая культура

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

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

Ссылки

  1. ^ "Создание операционной системы UNIX". Bell Labs. Архивировано из оригинала 14 сентября 2004 г.
  2. ^ ab McIlroy, MD (1987). Исследовательский ридер Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). CSTR. Bell Labs. 139.
  3. ^ Томпсон К , Ритчи ДМ (февраль 1973). Руководство программиста UNIX, третье издание (PDF) (технический отчет) (3-е изд.). Bell Labs. стр. 178.
  4. ^ Махони, Майкл С. «Проект устной истории Unix: Выпуск 0, Начало». Макилрой: Это было одно из немногих мест, где я почти осуществлял управленческий контроль над Unix, продвигал эти вещи, да.
  5. ^ "Пророческие петроглифы". www.bell-labs.com . Архивировано из оригинала 8 мая 1999 . Получено 22 мая 2022 .
  6. ^ "Pipes: A Brief Introduction". Linux Information Project. 23 августа 2006 г. [Создано 29 апреля 2004 г.] . Получено 7 января 2024 г. .
  7. ^ "Dartmouth Timesharing" (DOC) . Рочестерский технологический институт . Получено 7 января 2024 г.
  8. ^ "Data". www.bell-labs.com . Архивировано из оригинала 20 февраля 1999 . Получено 22 мая 2022 .
  9. ^ Кокс, Расс. "Bell Labs и CSP Threads". Switchboard . Получено 7 января 2024 г.
  10. ^ Ричи и Томпсон, 1974
  11. ^ "Заметки о выпуске Bash". tiswww.case.edu . Получено 2017-06-14 .
  12. ^ "Взаимодействие Shell Loop с SSH". 6 марта 2012 г. Архивировано из оригинала 6 марта 2012 г.
  13. ^ John1024. «Как сохранить результаты команды «find» в виде массива в Bash». Stack Overflow .{{cite web}}: CS1 maint: числовые имена: список авторов ( ссылка )

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