local 在标准流/裸字文件句柄上做了什么:STDIN?
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已关闭
这意味着如果发生错误,原始 fd 不会关闭。
我正在考虑做
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已关闭
这意味着如果发生错误,原始 fd 不会关闭。
- 使用