ページテーブルをコピーする必要があるため、親プロセスがより多くのメモリを使用すると、 fork(2)
呼び出しが遅くなります。 fork() の多くの一般的な使用法では、子プロセス ( Kernel#system
、 IO::popen
、 Process::spawn
など) を生成する関数の exec ファミリの 1 つが続きますが、このオーバーヘッドを削除することができます。特別なプロセス生成インターフェイス ( posix_spawn()
、 vfork()
など) を使用する
posix-spawn ライブラリは、高速プロセス生成インターフェイスが利用可能な場合はそれを利用し、そうでないシステムでは正常なフォールバックを提供する方法で、Ruby 1.9 Process::spawn
インターフェイスのサブセットを実装することを目的としています。
Process::spawn
インターフェースと、Ruby >= 1.8.7 でのKernel#system
、 Kernel#`
などの拡張バージョン (現在は MRI のみ) の大きな互換性のあるサブセット。POSIX::Spawn::Child
クラス。 次のベンチマークは、Linux 2.6 および MacOS X 上で常駐メモリ サイズを増やしたときに子プロセスをフォーク/実行するのに必要な時間を示しています。テストは、パッケージに含まれるposix-spawn-benchmark
プログラムを使用して実行されました。
posix_spawn
fork+exec
より高速で、 POSIX_SPAWN_USEVFORK
と一緒に使用すると一定時間で実行されます。
fork+exec
大規模な親プロセスの場合、非常に遅くなります。
posix_spawn
はfork+exec
より高速ですが、どちらも親プロセスのサイズの影響を受けません。
このライブラリには、2 つの異なるインターフェイスが含まれています。 POSIX::Spawn::spawn
、新しい Ruby 1.9 Process::spawn
メソッドに基づく下位レベルのプロセス生成インターフェイスであり、 POSIX::Spawn::Child
、簡単な生成を目的とした上位レベルのクラスです。単純な文字列ベースの標準入力/出力/エラー ストリーム処理を備えたプロセスの数。前者ははるかに多用途であり、後者は特定の一般的なシナリオで必要なコードがはるかに少なくなります。
POSIX::Spawn
モジュール (付属の C 拡張機能の助けを借りて) は、主に IEEE Std 1003.1 posix_spawn(2)
システム インターフェイスの使用を通じて、Ruby 1.9 Process::spawn インターフェイスのサブセットを実装します。これらは、さまざまな UNIX オペレーティング システムで広くサポートされています。
最も単純な形式では、 POSIX::Spawn::spawn
メソッドを使用して、 Kernel#system
と同様の子プロセスを実行できます。
require 'posix/spawn'
pid = POSIX::Spawn::spawn('echo', 'hello world')
stat = Process::waitpid(pid)
最初の行では、単一の引数を指定してecho
を実行し、新しいプロセスのpid
すぐに返します。 2 行目はプロセスが完了するのを待ち、 Process::Status
オブジェクトを返します。 spawn
、 system
のようにプロセスの実行が完了するのを待たず、子の終了ステータスを取得しないことに注意してください。Process Process::waitpid
(または同等のもの) を呼び出す必要があります。そうしないと、プロセスがゾンビになります。
spawn
メソッドは、新しいプロセスの環境の設定から、子の作業ディレクトリの変更、任意のファイル記述子のリダイレクトまで、多数の追加操作を実行できます。
詳細については Ruby 1.9 Process::spawn
ドキュメントを参照してください。また、 POSIX::Spawn::spawn
でサポートされているさまざまなProcess::spawn
機能の詳細については、以下のSTATUS
セクションを参照してください。
system
、 popen4
、および`
spawn
メソッドに加えて、 Kernel#system
とKernel#`
の Ruby 1.9 互換実装がPOSIX::Spawn
モジュールで提供されます。 popen4
メソッドを使用すると、リダイレクトされた stdin、stdout、および stderr オブジェクトを含むプロセスを生成できます。
POSIX::Spawn
モジュールをクラスやモジュールに混ぜて、その名前空間にspawn
とすべてのユーティリティ メソッドを含めることもできます。
require 'posix/spawn'
class YourGreatClass
include POSIX::Spawn
def speak(message)
pid = spawn('echo', message)
Process::waitpid(pid)
end
def calculate(expression)
pid, in, out, err = popen4('bc')
in.write(expression)
in.close
out.read
ensure
[in, out, err].each { |io| io.close if !io.closed? }
Process::waitpid(pid)
end
end
POSIX::Spawn::Child
クラスには、子プロセスを実行し、標準入力、出力、およびエラー ストリームからの読み取り/書き込みを行うためのロジックが含まれています。すべての入力を 1 つの文字列で受け取り、すべての出力を 1 つの文字列として提供するように設計されているため、コマンドの内外で大量のデータをストリーミングするのには適していません。そうは言っても、次のような利点があります。
select(2)
を使用) - 1 つ以上のストリームでのPIPE_BUF
制限の超過によるすべてのパイプ ハング ケースを処理します。 POSIX::Spawn::Child
インスタンス化時に標準のspawn
引数を受け取り、すべての入力を書き込み、すべての出力を読み取った後、プロセスを完了まで実行します。
>> require 'posix/spawn'
>> child = POSIX::Spawn::Child.new('git', '--help')
stdout / stderr に書き込まれたプロセス出力を取得するか、プロセスの終了ステータスを検査します。
>> child.out
=> "usage: git [--version] [--exec-path[=GIT_EXEC_PATH]]n ..."
>> child.err
=> ""
>> child.status
=> #<Process::Status: pid=80718,exited(0)>
:input
オプションを使用して、生成直後に新しいプロセスの stdin にデータを書き込みます。
>> child = POSIX::Spawn::Child.new('bc', :input => '40 + 2')
>> child.out
"42n"
追加のオプションを使用して、子プロセスが中止されるまでの最大出力サイズ ( :max
) と実行時間 ( :timeout
) を指定できます。詳細については、 POSIX::Spawn::Child
ドキュメントを参照してください。
POSIX::Spawn::Child.new
インスタンス化されるとすぐにプロセスを生成します。その結果、例外 (最大出力サイズ、時間制限、または別の要因に達することによる) によって中断された場合、コンストラクターが完了していないため、 out
またはerr
結果にアクセスすることはできません。
プロセスが中断されたときにout
およびerr
データが利用可能であったことを取得したい場合は、 POSIX::Spawn::Child.build
代替フォームを使用して、プロセスをすぐに生成せずに子を作成します。 exec!
例外をキャッチできる場所でコマンドを実行するには、次のようにします。
>> child = POSIX::Spawn::Child.build('git', 'log', :max => 100)
>> begin
?> child.exec!
?> rescue POSIX::Spawn::MaximumOutputExceeded
?> # limit was reached
?> end
>> child.out
"commit fa54abe139fd045bf6dc1cc259c0f4c06a9285bbn..."
MaximumOutputExceeded
例外が発生すると、内部バッファリングにより、実際に結合されたout
データとerr
データが:max
値よりも少し長くなる可能性があることに注意してください。
POSIX::Spawn::spawn
メソッドは、Ruby 1.9 のProcess::spawn
と可能な限り互換性があるように設計されています。現時点では互換性のあるサブセットです。
これらのProcess::spawn
引数は現在、 Spawn::spawn
、 Spawn::system
、 Spawn::popen4
、およびSpawn::Child.new
のいずれかでサポートされています。
env: hash
name => val : set the environment variable
name => nil : unset the environment variable
command...:
commandline : command line string which is passed to a shell
cmdname, arg1, ... : command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
clearing environment variables:
:unsetenv_others => true : clear environment variables except specified by env
:unsetenv_others => false : don't clear (default)
current directory:
:chdir => str : Not thread-safe when using posix_spawn (see below)
process group:
:pgroup => true or 0 : make a new process group
:pgroup => pgid : join to specified process group
:pgroup => nil : don't change the process group (default)
redirection:
key:
FD : single file descriptor in child process
[FD, FD, ...] : multiple file descriptor in child process
value:
FD : redirect to the file descriptor in parent process
:close : close the file descriptor in child process
string : redirect to file with open(string, "r" or "w")
[string] : redirect to file with open(string, File::RDONLY)
[string, open_mode] : redirect to file with open(string, open_mode, 0644)
[string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
FD is one of follows
:in : the file descriptor 0 which is the standard input
:out : the file descriptor 1 which is the standard output
:err : the file descriptor 2 which is the standard error
integer : the file descriptor of specified the integer
io : the file descriptor specified as io.fileno
以下のオプションは現在サポートされていません。
options: hash
resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
:rlimit_resourcename => limit
:rlimit_resourcename => [cur_limit, max_limit]
umask:
:umask => int
redirection:
value:
[:child, FD] : redirect to the redirected file descriptor
file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
:close_others => false : inherit fds (default for system and exec)
:close_others => true : don't inherit (default for spawn and IO.popen)
Posix::Spawn::Child、Posix::Spawn#spawn、Posix::Spawn#system、および Posix::Spawn#popen4 によって提供される:chdir
オプションは、プロセスが posix_spawn(2) システム コールで生成されるため、スレッドセーフではありません。呼び出しプロセスの作業ディレクトリを継承します。 posix-spawn gem は、子プロセスを生成する直前と直後に呼び出しプロセスの作業ディレクトリを変更することで、システム コールのこの制限を回避します。
著作権 (c) は Ryan Tomayko および Aman Gupta によって作成されます。
ライセンスと再配布の詳細については、 COPYING
ファイルを参照してください。