Spec-Zone.ru › Elixir 1.5

Порт

Функции для взаимодействия с внешним миром через порты.

Порты предоставляют механизм для запуска процессов операционной системы, внешних по отношению к Erlang VM, и взаимодействия с ними посредством обмена сообщениями.

Пример

END_OF_DOCUMENT_MARKER

В приведённом примере мы создали новый порт, выполняющий программу cat. cat — это программа, доступная в системах UNIX, которая получает данные с нескольких входов и конкатенирует их на выходе.

После создания порта мы отправили ему два команды в виде сообщений, используя Kernel.send/2. Первая команда содержит двоичную нагрузку «hello», а вторая — «world».

После отправки этих двух сообщений, мы вызвали помощника IEx flush(), который напечатал все полученные от порта сообщения, в данном случае «hello» и «world». Обратите внимание, что сообщения находятся в двоичном формате, поскольку мы передали :binary опцию при открытии порта в Port.open/2. Без такой опции, на выходе получился бы список байтов.

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

Elixir предоставляет множество удобств для работы с портами, а также некоторые недостатки. Мы рассмотрим их ниже.

API сообщений и функций

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

Ниже перечислены поддерживаемые портами сообщения и соответствующие им функции API:

  • {pid, {:command, binary}} — отправляет заданные данные в порт. См. command/3.

  • {pid, :close} — закрывает порт. Если порт ещё не закрыт, порт ответит сообщением {port, :closed} после очистки своих буферов и фактического закрытия. См. close/1.

  • {pid, {:connect, new_pid}} — устанавливает new_pid в качестве нового владельца порта. После открытия порта, порт связан и подключен к вызывающему процессу, и взаимодействие с портом происходит только через подключенный процесс. Это сообщение делает new_pid новым подключённым процессом. Если порт не завершён, порт ответит старому владельцу сообщением {port, :connected}. См. connect/2.

В свою очередь, порт отправит подключённому процессу следующие сообщения:

  • {port, {:data, data}} — данные, отправленные портом
  • {port, :closed} — ответ на сообщение {pid, :close}
  • {port, :connected} — ответ на сообщение {pid, {:connect, new_pid}}
  • {:EXIT, port, reason} — сигналы завершения в случае сбоя порта. Если reason не :normal, это сообщение будет получено только если владелец процесса обрабатывает завершения

Механизмы открытия

Порт можно открыть четырьмя основными способами.

В качестве краткого резюме, предпочтительнее использовать опции :spawn и :spawn_executable, упомянутые ниже. Остальные две опции, :spawn_driver и :fd, предназначены для расширенного использования внутри VM. Также рассмотрите использование System.cmd/3, если всё, что вам нужно, это запуск программы и получение её возвращаемого значения.

spawn

Кортеж :spawn получает двоичные данные, которые будут исполнены как полное вызов. Например, мы можем использовать его для прямого вызова «echo hello»:

END_OF_DOCUMENT_MARKER

:spawn извлечёт имя программы из аргумента и переберётся по переменной окружения $PATH вашего ОС в поисках соответствующей программы.

Хотя это удобно, это означает, что невозможно вызвать исполняемый файл, имя которого или любого из его аргументов содержит пробелы. По этим причинам, большинство случаев предпочтительнее использовать :spawn_executable.

spawn_executable

Spawn executable — это более ограниченная и явная версия spawn. Она ожидает полные пути к исполняемому файлу, который вы хотите запустить. Если они находятся в вашей $PATH, их можно получить, вызвав System.find_executable/1:

END_OF_DOCUMENT_MARKER

При использовании :spawn_executable, список аргументов можно передать через опцию :args, как показано выше. Полный список опций см. в документации функции Erlang :erlang.open_port/2.

spawn_driver

Spawn driver используется для запуска драйверов портов, которые представляют собой программы, написанные на C, реализующие определённые протоколы связи и динамически связанные с Erlang VM. Драйверы портов — это продвинутая тема и один из механизмов интеграции кода C наряду с NIF. Для получения дополнительной информации, пожалуйста, обратитесь к документации Erlang по ссылке.

fd

Опция имени :fd позволяет разработчикам получить доступ к in и out дескрипторов файлов, используемых Erlang VM. Вы будете использовать их только в том случае, если вы переписываете основную часть системы выполнения, например, процессы :user и :shell.

Процессы-зомби

Порт может быть закрыт с помощью функции close/1 или отправкой сообщения {pid, :close}. Однако, если VM аварийно завершит работу, долго выполняемая программа, запущенная портом, будет иметь закрытыми каналы stdin и stdout, но не будет автоматически завершена.

Хотя большинство инструментов командной строки UNIX завершат работу, как только их каналы связи будут закрыты, не все приложения командной строки будут делать так. Хотя мы рекомендуем плавное завершение, определяя, был ли stdin/stdout закрыт, у нас не всегда есть контроль над тем, как 3-х стороннее ПО завершает работу. В таких случаях, вы можете обернуть приложение в скрипт, который проверяет stdin. Вот такой скрипт на bash:

END_OF_DOCUMENT_MARKER

Теперь вместо:

END_OF_DOCUMENT_MARKER

Вы можете вызвать:

END_OF_DOCUMENT_MARKER

Резюме

Типы

name()

Функции

close(port)

Закрывает port

command(port, data, options \\ [])

Отправляет data в драйвер порта port

connect(port, pid)

Связывает идентификатор port с pid

info(port)

Возвращает информацию о port или nil если порт закрыт

info(port, spec)

Возвращает информацию о port или nil если порт закрыт

list()

Возвращает список всех портов в текущем узле

open(name, settings)

Открывает порт, используя кортеж name и список options

Типы

name()

END_OF_DOCUMENT_MARKER

Функции

close(port)

END_OF_DOCUMENT_MARKER

Закрывает port.

Для получения дополнительной информации, см. :erlang.port_close/1.

Вставлено компилятором.

command(port, data, options \\ [])

END_OF_DOCUMENT_MARKER

Отправляет data в драйвер порта port.

Для получения дополнительной информации, см. :erlang.port_command/2.

Вставлено компилятором.

connect(port, pid)

END_OF_DOCUMENT_MARKER

Связывает идентификатор port с pid.

Для получения дополнительной информации, см. :erlang.port_connect/2.

Вставлено компилятором.

info(port)

Возвращает информацию о port или nil если порт закрыт.

Для получения дополнительной информации, см. :erlang.port_info/1.

info(port, spec)

END_OF_DOCUMENT_MARKER

Возвращает информацию о port или nil если порт закрыт.

Для получения дополнительной информации, см. :erlang.port_info/2.

list()

END_OF_DOCUMENT_MARKER

Возвращает список всех портов в текущем узле.

Вставлено компилятором.

open(name, settings)

END_OF_DOCUMENT_MARKER

Открывает порт, используя кортеж name и список options.

В документации модуля выше содержатся документация и примеры поддерживаемых name значений, которые подведены в таблице ниже:

  • {:spawn, command} — запускает внешнюю программу. command должен содержать имя программы и, необязательно, список аргументов, разделённых пробелами. Если передаются программы или аргументы с пробелами в их имени, используйте следующую опцию.
  • {:spawn_executable, filename} — запускает исполняемый файл, указанный абсолютным путём filename. Аргументы могут быть переданы через опцию :args.
  • {:spawn_driver, command} — запускает так называемые драйверы портов.
  • {:fd, fd_in, fd_out} — получает доступ к дескрипторам файлов, fd_in и fd_out открытых VM.

Для получения дополнительной информации и списка опций, см. :erlang.open_port/2.

Вставлено компилятором.

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.5.3/Port.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API