[英]What does local do on the standard streams / bareword word filehandles: STDIN?
我正在考慮做
open(*STDIN, "<", "/dev/null" );
open(my $fh, "-|", "/bin/bash", "/tmp/foo");
print for <$fh>;'
但是,我想在之后恢復*STDIN
,所以我嘗試了。
{
open(local *STDIN, "<", "/dev/null" );
open(my $fh, "-|", "/bin/bash", "/tmp/foo");
print for <$fh>;
}
您可以使用cat
嘗試使用和不使用local
關鍵字這樣的方法,
{
# remove local and it works,
open(local *STDIN, "<", "/dev/null" );
open(my $fh, "-|", "/bin/cat");
print for <$fh>;
}
只有沒有local
才會cat
從/dev/null
讀取。 那么local
在裸字文件句柄上實際上做了什么?
open ...,'-|'
從標准輸入讀取的system
調用將嘗試從文件描述符 0 讀取。如果您不搞砸,外部程序將從與 perl 的標准輸入相同的輸入流中讀取。
# reads from standard input
open my $fh, '-|', "/bin/cat";
while (<fh>) { print }
# reads from /tmp/foo
open STDIN, "<", "/tmp/foo"; # replaces fd0 with handle to /tmp/foo
open my $fh, '-|', "/bin/cat";
while (<$fh>) { print }
# reads from standard input
open local *STDIN, "<", "/tmp/foo"; # doesn't close fd0, creates new fd
open my $fh, '-|', "/bin/cat";
while (<$fh>) { print }
# reads from /tmp/foo
close STDIN;
open FOO, "<", "/tmp/foo"; # fileno(FOO) should be 0 now
open my $fh, '-|', "/bin/cat";
while (<$fh>) { print }
有系統文件句柄(稱為文件描述符,或“fd”),還有 Perl 文件句柄。 Perl 文件句柄通常包裝系統文件句柄,但情況並非總是如此。 例如, open(my $fh, '<', \\$buf)
創建一個與任何系統文件句柄無關的 Perl 句柄。
其他進程對您的進程變量一無所知,因此它們對 Perl 文件句柄一無所知。 任何作為 fd 0 打開的句柄都將用作 STDIN,fd 1 作為 STDOUT,而 fd 2 作為 STDERR。 [1]
當open
傳遞一個現有的 Perl 句柄時,這個句柄將被關閉。 如果創建一個新的系統文件句柄,它將被賦予與原始 fd 相同的編號(如果原始句柄有一個)或最低的可用編號(如果沒有)。 [2]
因此,當您使用open(*STDIN, ...)
,與*STDIN{IO}
關聯的新句柄也將是 fd 0。
$ perl -e'
CORE::say fileno(*STDIN);
open(*STDIN, "<", "/dev/null") or die $!;
CORE::say fileno(*STDIN);
'
0
0
cat
從 fd 0 讀取,因此會注意到變化。
local *STDIN
創建 glob 的備份並將*STDIN
與新的 glob 關聯。 原始*STDIN
仍在內存中,因此沒有釋放與*STDIN
關聯的資源。 這意味着與*STDIN
關聯的任何文件句柄仍處於打開狀態。
當您使用open(local *STDIN, ...)
,新的 fd 將具有可用的最低數字。 fd 0 仍在內存中某個地方的原始*STDIN
使用,因此 fd 0 不可用。 也許這次 fd 3 將是第一個可用的 fd(STDOUT 和 STDERR 使用 1 和 2)。
$ perl -e'
CORE::say fileno(*STDIN);
{
open(local *STDIN, "<", "/dev/null") or die $!;
CORE::say fileno(*STDIN);
}
CORE::say fileno(*STDIN);
'
0
3
0
cat
從 fd 0 讀取,將從原始句柄讀取。
Perl 可以使與 STDIN、STDOUT 和 STDERR 關聯的任何句柄在執行cat
之前變為 fd 0、1 和 2,但事實並非如此。 這是留給你的。
當我描述 unixy 系統中的工作方式時,Windows 中的工作方式類似。
在open
傳遞一個包裝系統文件句柄的句柄並且也正在創建一個新的系統文件句柄的情況下,unixy 系統上使用的內部機制如下:
open
創建一個新的 fd。 它將具有最低的可用數字。dup2
用於創建與原始 fd 具有相同編號的新 fd 的副本。open
創建的 fd 是關閉的。這意味着如果發生錯誤,原始文件不會關閉。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.