perlfork - クラウド上のオンライン

これは、Ubuntu Online、Fedora Online、Windows オンライン エミュレーター、または MAC OS オンライン エミュレーターなどの複数の無料オンライン ワークステーションの XNUMX つを使用して、OnWorks 無料ホスティング プロバイダーで実行できるコマンド perlfork です。

プログラム:

NAME


perlfork - Perl の fork() エミュレーション

SYNOPSIS


注: 5.8.0 リリースの時点で、fork() エミュレーションは大幅に改善されました。
成熟した。 ただし、既知のバグと相違点がまだいくつかあります
あなたに影響を与える可能性のある実際の fork() から。 「バグ」を参照してください。
以下の「注意事項と制限事項」セクションを参照してください。

Perl が提供するのは、 フォーク() 同じ名前の Unix システム コールに対応するキーワード。
ほとんどの Unix 系プラットフォームでは、 フォーク() Perlのシステムコールが利用可能 フォーク()
単にそれを呼び出すだけです。

Windows などの一部のプラットフォームでは、 フォーク() システムコールは使用できませんが、Perl では使用できます。
エミュレートするために構築される フォーク() 通訳レベルで。 エミュレーションは次のように設計されていますが、
可能な限り実物と互換性があること フォーク() Perl プログラムのレベルでは、
いくつかの重要な違いは、すべての疑似子供が存在するという事実から生じます。
この方法で作成された「プロセス」は、オペレーティング システムまで同じ実際のプロセス内に存在します。
心配している。

この文書では、の機能と制限の概要を説明します。
フォーク() エミュレーション。 ここで説明する問題はプラットフォームには当てはまらないことに注意してください。
ここで本物 フォーク() が利用可能であり、Perl はそれを使用するように構成されています。

DESCRIPTION


この フォーク() エミュレーションは Perl インタプリタのレベルで実装されます。 これが何を意味するか
一般的に、それは実行中です フォーク() 実際には、実行中のインタープリタとそのすべてのクローンを作成します。
状態を取得し、複製されたインタプリタを別のスレッドで実行し、新しいスレッドで実行を開始します。
ポイントの直後のスレッド フォーク() 親に呼ばれた。 参考にさせていただきます
この子「プロセス」を疑似プロセスとして実装するスレッド。

呼び出した Perl プログラムに対して フォーク()、これらはすべて透明になるように設計されています。 の
親が学校から帰ってくる フォーク() 後で使用できる疑似プロセス ID が付いている
プロセス操作関数。 子供がそこから帰ってくる フォーク() 値は 0 ~
それが子疑似プロセスであることを示します。

行動 of 他の パール 機能を使用 in 二股 疑似プロセス
ほとんどの Perl 機能は、疑似プロセス内で自然な方法で動作します。

$$ または $PROCESS_ID
この特殊変数は疑似プロセス ID に正しく設定されます。 使用できます
特定のセッション内の疑似プロセスを識別します。 この値は次のとおりであることに注意してください。
他の疑似プロセスが起動された後に疑似プロセスが起動された場合、リサイクルの対象となります。
待つ()-ed on。

%ENV 各擬似プロセスは独自の仮想環境を維持します。 %ENV の変更
仮想環境に影響を与え、その疑似プロセス内でのみ表示されます。
そして、そこから起動されるプロセス (または疑似プロセス) 内でも同様です。

chdir() およびファイル名を受け入れる他のすべての組み込み関数
各疑似プロセスは、現在のディレクトリの独自の仮想概念を維持します。
を使用して現在のディレクトリを変更します。 chdir() その中でしか見えない
疑似プロセス、およびそこから起動される任意のプロセス (または疑似プロセス)。 全て
疑似プロセスからのファイルとディレクトリへのアクセスは、仮想プロセスを正しくマップします。
作業ディレクトリを実際の作業ディレクトリに適切に変更します。

待つ() および waitpid()
待つ() および waitpid() によって返される疑似プロセス ID を渡すことができます。 フォーク()。 これら
呼び出しは擬似プロセスの終了を適切に待機し、その擬似プロセスを返します。
状態。

殺す() 「kill('KILL', ...)」は、ID を渡すことで疑似プロセスを終了するために使用できます。
によって返される フォーク()。 疑似プロセスでの kill の結果は予測不可能であり、
悲惨な状況以外では使用しないでください。
システムは、スレッドの実行中にプロセス リソースの整合性を保証できない可能性があります。
終了されます。 疑似プロセスを実装するプロセスをブロックできる
Perl インタプリタがハングします。 「kill('KILL', ...)」を使用することに注意してください。
擬似-処理する() 通常、メモリ リークが発生する可能性があります。
擬似プロセスを実装すると、そのリソースをクリーンアップする機会が得られません。

「kill('TERM', ...)」は疑似プロセスでも使用できますが、シグナルは使用されません。
疑似プロセスがシステムコールによってブロックされている間に配信される(待機中など)
ソケットを接続するか、使用可能なデータがないソケットから読み取ろうとしています。
Perl 5.14 以降、親プロセスは子プロセスが一度終了するのを待ちません。
プロセス中のデッドロックを回避するために、「kill('TERM', ...)」でシグナルが送られています。
出口。 明示的に呼び出す必要があります waitpid() 子供に時間を確保するために
自分で片づけるのは自分自身ですが、その場合、子供が片づけない責任もあなたにあります。
I/O のいずれかをブロックします。

exec() 呼び出し exec() 疑似プロセス内で、要求された実行可能ファイルが実際に生成されます。
別のプロセスを実行し、そのプロセスが完了するまで待機してから、同じ出口で終了します。
そのプロセスとしてのステータス。 これは、プロセス ID が
実行可能ファイルは以前の Perl とは異なります。 フォーク() かもしれない
戻ってきた。 同様に、ID に適用されるプロセス操作関数
によって返される フォーク() を呼び出した待機中の疑似プロセスに影響します。 exec()はなく、
の後に待っている実際のプロセス exec().

日時 exec() 疑似プロセス内で呼び出され、DESTROY メソッドと END ブロックが呼び出されます。
外部プロセスが戻った後も呼び出されます。

出口() 出口() 常に実行中の疑似プロセスのみを終了し、その後自動的に終了します。
待つ()未処理の子疑似プロセスに対して -ing を実行します。 これは次のことを意味することに注意してください
実行中のすべての疑似プロセスが終了しない限り、プロセス全体は終了しません。
出ました。 開いているファイルハンドルに関するいくつかの制限については、以下を参照してください。

ファイル、ディレクトリ、ネットワークソケットへのハンドルを開く
開いているハンドルはすべて、 dup()疑似プロセスで -ed を実行するため、ハンドルが閉じられます。
XNUMX つのプロセスが他のプロセスに影響を与えることはありません。 いくつかの制限については以下を参照してください。

Resource 制限
オペレーティング システムの目には、 フォーク() エミュレーションは
単に同じプロセス内のスレッドです。 これは、プロセス レベルの制限が課されることを意味します。
オペレーティング システムは、すべての疑似プロセスをまとめて適用します。 これにはあらゆるものが含まれます
開いているファイル、ディレクトリ、およびソケットの数に対してオペレーティング システムによって課される制限
ハンドル、ディスクスペース使用量の制限、メモリサイズの制限、CPU 使用率の制限など。

殺害   プロセス
親プロセスが (Perl のいずれかを使用して) 強制終了された場合 殺す() 組み込み、または一部を使用
外部手段) すべての疑似プロセスも強制終了され、プロセス全体が終了します。

永続ライセンス of   プロセス および 疑似プロセス
通常のイベントの過程で、親プロセスとすべての疑似プロセスは、
それぞれの擬似子が完了するまで待ってから終了します。 これ
親と、その親によって作成されたすべての擬似子 (擬似親でもある) を意味します
は、擬似子が終了した後にのみ終了します。

Perl 5.14 以降では、親は機能しません。 待つ() これまでに行われたすべての子供に対して自動的に
子がブロックしている場合にデッドロックを回避するために、「kill('TERM', ...)」で通知されます。
I/O を行いますが、信号を受信することはありません。

警告 そして 制限


BEGIN ブロック
この フォーク() エミュレーションは、内部から呼び出された場合、完全に正しく動作しません。
ブロックを開始します。 フォークされたコピーは BEGIN ブロックの内容を実行しますが、
BEGIN ブロックの後にソース ストリームの解析を続行しません。 例えば、
次のコードを考えてみましょう。

ベギン {
分岐して出口。 # 子をフォークして親を終了します
"内側\n" を印刷します。
}
"外側" を印刷します\n;

これは次のように出力します:

内側の

予想されるものではなく、

内側の
外側の

この制限は、クローン作成および
解析の途中で Perl パーサーによって使用されるスタックを再起動します。

ファイルハンドルを開く
実行時に開いているファイルハンドルはすべて、 フォーク() なります dup()-編。 したがって、ファイルは
親と子で独立して閉じることができますが、 dup()した
ハンドルは引き続き同じシーク ポインタを共有します。 シーク位置を変更する
親が子でそれを変更し、その逆も同様です。 開くことでこれを回避できます
子ファイルで個別のシーク ポインターを必要とするファイル。

一部のオペレーティング システム、特に Solaris と Unixware では、
子プロセスは親で開いているファイルハンドルをフラッシュして閉じます。
ファイルハンドルを破損します。 これらのシステムでは、「_exit()」を呼び出すことをお勧めします。
その代わり。 「_exit()」は、「POSIX」モジュールを介して Perl で使用できます。 お願いします
詳細については、システムのマンページを参照してください。

ディレクトリハンドルを開く
Perl は、開いているすべてのディレクトリ ハンドルを最後に到達するまで完全に読み取ります。
ストリームの。 そうすれば、 seekdir() 元の場所に戻ってすべて
未来 readdir() リクエストはキャッシュ バッファから処理されます。 つまり、
親プロセスが保持するディレクトリ ハンドルも、親プロセスが保持するディレクトリ ハンドルも
子プロセスは、ディレクトリに加えられた変更を確認します。 フォーク()
コール。

注意してください rewinddir() Windows にも同様の制限があり、強制はされません。
readdir() ディレクトリを再度読み取るか、 新しく開いたディレクトリのみ
ハンドルはディレクトリへの変更を反映します。

分岐パイプ 開いた() まだ実装されていません
「open(FOO, "|-")」および「open(BAR, "-|")」構造はまだ実装されていません。
この制限は、新しいコードでパイプを作成することで簡単に回避できます。
明示的に。 次の例は、フォークされた子に書き込む方法を示しています。

# open(FOO, "|-") をシミュレートします
サブパイプからフォークへ ($) {
私の $parent = シフト;
$child、$parent、または die をパイプします。
私の $pid = fork();
「fork() が失敗しました: $!」 $pid が定義されていない限り;
if ($pid) {
$child を閉じます。
}
他{
$parentを閉じます。
open(STDIN, "<&=" . fileno($child)) または die;
}
$pid;
}

if (pipe_to_fork('FOO')) {
# 親
print FOO "pipe_to_fork\n";
FOOを閉じます。
}
他{
# 子供
その間 ( ) { 印刷; }
終了する(0);
}

そして、これは子供から次のように読み上げられます。

# open(FOO, "-|") をシミュレートします
サブパイプからフォーク ($) {
私の $parent = シフト;
$parent、my $child、または die をパイプします。
私の $pid = fork();
「fork() が失敗しました: $!」 $pid が定義されていない限り;
if ($pid) {
$child を閉じます。
}
他{
$parentを閉じます。
open(STDOUT, ">&= . fileno($child)) または die;
}
$pid;
}

if (pipe_from_fork('BAR')) {
# 親
その間 ( ) { 印刷; }
BARを閉じる。
}
他{
# 子供
print "pipe_from_fork\n";
終了する(0);
}

分岐パイプ 開いた() 構造は将来サポートされる予定です。

XSUB によって維持されるグローバル状態
独自のグローバル状態を維持する外部サブルーチン (XSUB) が機能しない可能性がある
正しく。 このような XSUB は、同時接続を保護するためにロックを維持する必要があります。
さまざまな擬似プロセスからグローバル データにアクセスするか、それらのすべての状態を維持します
Perl シンボル テーブル上。これは、次の場合に自然にコピーされます。 フォーク() と呼ばれます。 あ
拡張機能にその状態を複製する機会を提供するコールバック メカニズム
近い将来提供される予定です。

より大きなアプリケーションに組み込まれたインタプリタ
この フォーク() エミュレーションは、次の環境で実行すると期待どおりに動作しない可能性があります。
Perl インタープリターを組み込み、評価できる Perl API を呼び出すアプリケーション
Perl コードのビット。 これは、エミュレーションには知識しかないという事実に起因します。
Perl インタプリタ自身のデータ構造については何も知りません。
アプリケーションの状態が含まれます。 たとえば、
アプリケーション自体の呼び出しスタックにはアクセスできません。

拡張機能のスレッドセーフ
から フォーク() エミュレーションは複数のスレッドでコードを実行し、拡張機能は
非スレッドセーフなライブラリは、呼び出し時に確実に動作しない可能性があります フォーク()。 Perl のように
スレッドのサポートは、
ネイティブ フォーク()、そのような拡張機能はスレッドセーフのために修正される予定です。

移植性 警告


移植可能な Perl コードでは、フォークされたプロセスで「kill(9, $child)」を使用してはなりません。 を殺す
フォークされたプロセスは安全ではなく、予測できない結果をもたらします。 見る "殺す()"、 その上。

onworks.net サービスを使用してオンラインで perlfork を使用する



最新のLinuxおよびWindowsオンラインプログラム