3

問題は次のとおりです。クライアントから要求を取得し、要求に応じて(一部のモジュールから)関数を実行し、クライアントに応答を返すデーモンがあります。fork()の後、STDIN、STDOUT、およびSTDERRを閉じます。1つの機能はdmesgをチェックすることです。このために、open(DMESG、 "/ bin / dmesg |")を介してdmesg出力を取得します。関数が終了すると自動的に閉じると思ったので、読んだ後は閉じません。しかし、これは発生せず、dmesgを呼び出すたびにゾンビが発生します。

PerlのSTDIN /STDOUT / STDERRを再初期化するにはどうすればよいですか?「再度開く代わりにSTDOUTを閉じる場合の問題は、他のファイルを開くと、fd 0、1、または2になる可能性があるため、将来STDOUTを再度開くことができないことです。」by jmanning2kそして、それはそれと関係があると思いますが、私は実際にはそれを理解していません。誰かが私にそれを説明してくれることを願っています。

たとえば、qx()を介してdmesgを呼び出すことで、問題を回避できることを知っています。または単にfhを閉じますが、ゾンビがどこから来ているのかを理解したいと思います。

4

3 に答える 3

7

フォーム

open DMESG, "/bin/dmesg|";

パイプを開き、動的スコープの変数に割り当てますDMESG。動的にスコープされた変数は、実際にはPerlで「永久に」存続し、alocalが表示されるたびに必要に応じて保存されます。

代わりにフォームを使用する場合

open my $dmesg, "/bin/dmesg|";

字句ファイルハンドル変数は、スコープの終了時に閉じられます。$dmesgこれは、それを存続させる理由が他にない場合(つまり、渡されないか、グローバル変数に格納されない場合)です。

于 2010-12-15T15:11:36.037 に答える
6

open(DMESG, "/bin/dmesg |") 関数が終了すると自動的に閉じると思ったので、読んだ後は閉じません。

これが機能するためには、ハンドルが字句である必要があります。これにより、ハンドルが適切にスコープから外れる可能性があります。

open my $dmesg, …
于 2010-12-15T15:10:56.850 に答える
1

問題は、Perlの実装方法に関係しています。Perl_do_opennこれがファイル内の関数からのコードの一部ですdoio.c

fd = PerlIO_fileno(IoIFP(io));
if (IoTYPE(io) == IoTYPE_STD) {
    /* This is a clone of one of STD* handles */
    result = 0;
}
else if (fd >= 0 && fd <= PL_maxsysfd) {
    /* This is one of the original STD* handles */
    saveifp  = IoIFP(io);
    saveofp  = IoOFP(io);
    savetype = IoTYPE(io);
    savefd   = fd;
    result   = 0;
}

既存のファイルハンドルを開くと、ファイルハンドルが閉じられ、によって再度開かれopen()ます。STD*上記のコードからわかるように、これはハンドルでは発生しません。したがって、Perlは開くために次のフリーハンドルを取り、古いハンドルは開いたままになります。

于 2010-12-15T16:24:57.153 に答える