複数プロセスでの値のやりとりについて
複数プロセスでの処理を簡易的に行う場合、
私は、forkやParallel::ForkManagerを使いますが、
forkした複数の処理結果を共有する亊ができないため、
これまで、プロセス間通信を行うIPC::ShareableやIPC::Liteを使って、
forkした結果を共有できるようにしていました。
ただ、IPC系モジュールの挙動をあまり理解できていなかったため、
理解を深められたらとこのエントリーを書いてみました。
例ですが、perlモジュールのバージョンをチェックするスクリプトです。
モジュール名をfork関数を使って1プロセスずつ問い合わせ、結果をIPC::Liteモジュールで定義したグローバル変数に追加をしています。
use strict; use IPC::Lite qw($result); $result = undef; my @name_list = qw( DBI CGI LWP::Simple ); foreach ( @name_list ){ my $pid = fork; if ($pid) { wait; } else { $result->{$_} = &working_process($_); exit(0); } } sub working_process { my $module = shift; my $required_module = $module; $required_module =~ s{::}{/}g; eval { require "$required_module.pm"; }; if ($@) { return "not_installed"; } else { no strict 'refs'; return ${$module."::VERSION"}; } } use Data::Dumper; print Dumper( $result ); ## resultに格納した値は処理の最終的にクリアしておきたいので... foreach( keys %$result ){ $result->{$_} = undef; } 1;
IPCと名の付くモジュールの中で、今回はIPC::Liteの挙動を理解したかったので、モジュールを少し読んでみました。
上記の例では、各プロセスで取得したperlモジュールのバージョン値をプロセス間で共有するために、IPC::Liteではたいへんザックリですが、以下のような流れで処理されていると理解しました。
1. IPC::Liteをuseする部分で、まず今処理しているパッケージ上のグローバル変数 「result」がtie関数でフックされる。
2. フックされた「result」をキーに各プロセスで取得したモジュールのモジュール名やバージョン値などを、SQLiteにinsertする。なお、2回目以降は、「result」という名でSQLiteに登録されているデータを取得し、登録されていないものがあれば、追加でinsertを行う。
IPCを理解するには、まだ程遠い気がしますが、IPC系のモジュールももっと数多く読んで理解を深めていけたらと思います。
勘違いなどありましたら、ご指摘いただければありがたいです。
よろしくお願い致します。