LoginSignup
7
7

More than 5 years have passed since last update.

open_port 日本語ドキュメント

Posted at

はじめに

open_portの全仕様が書かれた日本語のドキュメントが見つからなかったため、自分で書くことにした。

(勉強も兼ねて。)

以下のドキュメントを素にしている。

公式ドキュメント(もちろん英語)
http://erlang.org/doc/man/erlang.html#open_port-2

Spec

spec.hrl
-spec open_port(PortName, PortSettings) -> port() when
      PortName :: {spawn, Command :: string() | binary()}
                | {spawn_driver, Command :: string() | binary()}
                | {spawn_executable, FileName :: file:name()}
                | {fd, In :: integer() >= 0, Out :: integer() >= 0},
      PortSettings :: [Opt],
      Opt :: {packet, N :: 1 | 2 | 4}
           | stream
           | {line, L :: integer() >= 0}
           | {cd, Dir :: string() | binary()}
           | {env, Env :: [{Name :: string(), Val :: string() | false}]}
           | {args, [string() | binary()]}
           | {arg0, string() | binary()}
           | exit_status
           | use_stdio
           | nouse_stdio
           | stderr_to_stdout
           | in
           | out
           | binary
           | eof
           | {parallelism, Boolean :: boolean()}
           | hide.

仕様

  • 新しいErlangポートを開いてポート識別子を返す
    • ポートは外部Erlangプロセスとして扱える
  • システムがUnicodeファイル名モードで実行されている場合、以下のものはすべてUnicodeファイル名変換の対象
    • 実行可能ファイル名
    • cdenvargsarg0 の引数
  • 変換を避ける、または、UTF-8に強制するためには

注意

  • ErlangのVMをUnicodeファイル名変換モードで起動した場合
    • 名前(Listの場合)の文字 > 255 のみ
  • そうでない場合
    • 実行可能ファイル名はISO-Latin-1文字セットに制限される

PortName

{spawn, Command}

  • 外部プログラムを起動
    • Command
      • 起動する外部プログラムの名前
      • 同名のErlangドライバが存在しない
        • Erlangのワークスペース外で Command を実行する
      • 同名のErlangドライバが存在する
        • そのドライバを起動
        • Erlangのワークスペース内で実行される
          = Erlangランタイムシステムにリンクされる
      • スペースで区切った最初のトークン
        = 実行可能ファイル(or ドライバ)の名前
        • ファイルまたはディレクトリ名にスペースを持つプログラムの実行に適さない
          → 代わりに {spawn_executable, Command} を使う
  • Solaris の場合
    • システムコールvforkが使われる
      • パフォーマンス上の理由でforkより優先される
      • 信頼性は低い
      • vforkを使うことに問題がある場合
        • 環境変数 ERL_NO_VFORK に任意の値をセット
          → forkを代わりに使うことができる
  • 実行時、 PATH を使う
    • OSによってはプログラムを見つけるために環境メソッドを使う
    • 特定プラットフォーム上でシェルを起動することによって決まる

{spawn_driver, Command}

  • {spawn, Command} のように動作
    • Command のスペース区切りトークンの最初
      ロードされたドライバの名前でないといけない
      • その名前のドライバがロードされていない場合
        • エラー badarg が発生

{spawn_executable, FileName}

  • {spawn, FileName} のように動作
    • 外部実行可能ファイルの実行しかできない
    • FileName
      • 全体で実行可能ファイルの名前
        • スペースを含む
      • 引数を渡す場合
        • PortSettingsargsarg0 を使う
  • シェルは直接実行される
    • 通常プログラムを起動するために呼び出されていない
    • PATH 等は検索されない
  • シェルスクリプトまたは .batファイルが実行された場合だけ
    → 適切なコマンドインタプリタが暗黙的に呼び出される
    • しかし、まだコマンドの引数の拡張、暗黙的な PATH の検索はされない
  • FileName が実行できない場合
    • POSIXのエラーコードとエラー例外が発生
      • エラーの理由はOS間で異なる可能性あり
      • 発生するエラー
        • enoent
          • 見つからないプログラムが実行されようとしたとき
        • eaccess
          • 与えられたファイルが実行可能でないとき

{fd, In, Out}

  • Erlangプロセスはファイルディスクリプタにアクセスすることができる
    • 対象のファイルディスクリプタ
      • 現在開いている
      • Erlangによって使用されている
      • In
        • 標準入力として使用することができる
      • Out
        • 標準出力として使用することができる
    • Erlang OS(shell, user)の様々なサーバでのみ利用される
      → 仕様は非常に限られる

PortSettings

{packet, N}

  • メッセージの先頭に長さが N バイト長で送られる
    • N
      • 1, 2, 4のどれかのみ

stream

  • 出力メッセージをパケット長なしで送信
  • ユーザ定義のプロトコルを使用しなければならない
    • Erlangプロセス - 外部オブジェクト間

{line, L}

  • メッセージが行ごとに配信される
    • それぞれの行は1つのメッセージで配信
      • 行: OS依存の改行文字で区切られている
  • メッセージのデータ形式は {Flag, Line}
    • Flag
      • eol または noeol
    • Line
      • 配信された実際のデータ
        • 改行文字を持たない
  • L
    • 最大の行の長さ
      • バイト単位
    • これよりも長い行は、複数のメッセージで送られる
      • Flagnoeol が設定されている
      • 最後のメッセージは eol
        • EOFが来たり、すぐに新しいシーケンスが続かなかったりした場合、 noeol
  • {packet, N}{line, L} は相互排他

{cd, Dir}

  • {spawn, Command}{spawn_executable, FileName} にのみ有効
  • 外部プログラムの作業ディレクトリが Dir になる
    • Dirstring()

{env, Env}

  • {spawn, Command}{spawn_executable, FileName} にのみ有効
  • 環境仕様に Env を追加
    • Env{Name, Val} のリスト
      • Name は 環境変数名
        • string()
      • Val は 生成されたポートプロセスで持つ値
        • string()
        • 例外として false が使える
          • 環境変数を除去
          • os:getenv/1 と同じ

{args, [string() | binary()]}

  • {spawn_executable, FileName} に有効
  • 実行可能ファイルに引数を指定
    • 各引数は別々の文字列として与えられる
    • Unix上
      • 引数ベクトルにおける一つの要素
    • 他のプラットフォーム
      • 似たような挙動
  • 引数はシェルによって展開されない
    • 特に注意すべきことは ワイルドカードが展開されないこと
      • ワイルドカードを展開するには filelib:wildcard/1 を使う
      • これはUnixシェルスクリプトでも同じ
        • ワイルドカードが展開されずに実行される
      • Windows®では、ワイルドカード展開はプログラム自身で行っているので問題にならない
  • 実際に実行するファイル名( argv[0] )はこのリストで指定しない
    • 適切な実行可能ファイル名が argv[0] として使われる
    • 何らかの理由で引数ベクトルにプログラム名を明示的に設定したい場合は argv[0] を使う

{arg0, string() | binary()}

  • {spawn_executable, FileName} でのみ有効
    • 実行可能ファイルを実行するときにプログラム名引数を明示的に指定
    • 一部のOSの特定の状況下では望ましい時がある
      • プログラムの返答の仕方はかなりシステムに依存
      • 具体的な影響は保証されない

exit_status

  • {spawn, Command}{spawn_executable, FileName} で有効
    • Command外部プログラム のみ
  • 外部プロセス終了時、 {Port, {exit_status, Status}} が送られる
    • Status は外部プロセスの終了ステータス
      • Unix上で以上終了した時はシェルと同じ規則
        • 128+signal
  • eof オプションが指定されている場合
    • eof メッセージと exit_status メッセージの順序は決まっていない
  • ポートプログラムが終了せず、標準出力を閉じた場合は、 exit_status は機能しない

use_stdio

  • {spawn, Command}{spawn_executable, FileName} で有効
    • (UNIX)プロセスの標準出入出力が使用可能になる
      • ファイルディスクリプタ0、1

nouse_stdio

  • use_stdio の逆
    • Erlangとの通信にファイルディスクリプタ3, 4を使用

stderr_to_stdout

  • 外部プログラムへのポートに影響
  • 標準エラー出力を標準出力に出す
  • stderr_to_stdoutnouse_stdio は相互排他

overlapped_io

  • 外部プログラムへのポートに影響
    • Windows® でのみ
  • ポートプログラムが標準入力と標準出力ハンドル上でオーバーラップされたI/Oを扱う
    • 標準ハンドルが FILE_FLAG_OVERLAPPED と一緒に開かれる
  • 単純なポートプログラム用で経験の豊富なWindowsプログラマのためのオプションではない
  • 他のプラットフォームでは無視される

in

  • 入力のためだけにポートが使える

out

  • 出力のためだけにポートが使える

binary

  • ポートからのすべてのI/Oが binary() になる

eof

  • portを開いたまま、 {Port, eof} メッセージをポートを保持しているプロセスに送信する

hide

  • ポートプログラムを起動するときに、新しいコンソールウィンドウを作らない
    • Windows上で実行している場合
    • 他のプラットフォームには影響を与えない

{parallelism, Boolean}

  • ポートの並列処理のためにスケジューラヒントを設定
    • true
      • システム内の並列性を向上させようとする
      • VMはシステム内で並列処理を改善するためにポートタスクをスケジューリングする
    • false
      • VMは並列性を犠牲にしてレイテンシを改善
      • すぐにポートのタスクを実行しようとする
  • デフォルトはerl起動時にコマンドライン引数+sppで設定
  • 対象
    • ポートのすべての型のためのstream
    • 生成されたポートのための use_stdio

エラー

  • ポートがオープンできない場合
    • badarg
    • ```system_limit
  • Posixのエラーコード
    • もっとも詳細にエラーを説明
  • 対応するPosixコードがない場合は einval

badarg

  • open_port の引数の問題

system_limit

  • Erlangエミュレータで利用できるポートがない

enomem

  • 十分なメモリがない
    • ポートを生成するための

eagain

  • 利用可能なOSのプロセスがない

enametoolong

  • 与えられた外部コマンドが長過ぎる

emfile

  • 利用可能なファイルディスクリプタがない
    • Erlangエミュレータが走るOSプロセスのための

enfile

  • ファイルテーブルがいっぱい
    • 全OS

eacces

  • {spawn_executable, Command} で与えられた Command が実行可能ファイルでない

enoent

  • {spawn_executable, FileName} で与えられた FileName が存在しない

{'EXIT', Port, PosixCode}

  • ポート使用時のエラー
  • ポートを使用しているプロセスに伝えられる
  • 対象
    • {spawn, Name}{spawn_driver, Name} または {spawn_executable, Name}
  • PosixCode の取り得る値については file (?) を参照
  • 同時に開くことができるポートの最大数
    • erl+Qコマンドラインフラグを渡すことによって設定

外部サイト

公式ドキュメント(もちろん英語)
http://erlang.org/doc/man/erlang.html#open_port-2

いろはメモ - Erlang 編 - 「は」 : ポートによる外部接続 - lnzntの Erlang 日記 - はてなグループ: erlang
http://erlang.g.hatena.ne.jp/lnznt/20110814/1313283961

書籍

  • 「プログラミングErlang」 には
    • 基本的な使い方の記述あり
    • 良く使われる PortNameOpt だけ紹介
  • 「すごいErlangゆかいに学ぼう」 は…
7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7