如果我们不在Perl中关闭文件,有多严重? 如果我在同一个程序中再次访问它会影响程序或文件吗?
答案 0 :(得分:12)
全局文件句柄将一直存在,直到您的程序退出。这可能很糟糕,但是你可能不应该使用全局文件句柄,这不是问题。
my
的词法文件句柄在其范围为左/其引用计数降至零时为close
d。
如果重新使用文件句柄的名称,则前一个文件句柄隐含close
d。以下脚本重复使用相同的文件句柄来打印任意数量文件的前五行:
my $fh;
foreach my $filename (@ARGV) {
open $fh, "<", $filename or die "Can't open $filename"; # $fh is re-used
print scalar <$fh> // next for 1 .. 5; # // is the defined-or
}
使用文件时,明确关闭FH并不重要。但是,在进行IPC时这一点至关重要。关闭管道的写入结束表示EOF到读取端。
当fork
时,应关闭所有未使用的文件句柄,因为它们在分叉时是重复的。这意味着在一个进程中关闭管道可能不会发送所需的EOF,因为相同的管道仍在相关进程中打开。
这是一个演示close
在IPC中的重要性的程序:
pipe my $out, my $in or die $!;
if (fork()) { # PARENT
close $out; # close unused handle (important!)
select $in;
$| = 1; # set $in to autoflushed (important!)
$SIG{PIPE} = sub {die "Parent"}; # die, when the pipe is closed
print ++$i, "\n" and sleep 1 while 1; # print one number per second
} else { # CHILD
close $in; # close unused handle
print scalar <$out> for 1 .. 5; # read numbers 1 to 5 from the pipe
close $out; # close the pipe (and trigger SIGPIPE)
sleep 5; # wait, then exit
die "Child";
}
此程序的输出是数字1到5.然后,子项关闭管道的末尾,在父项中触发SIGPIPE
。当父母去世时,孩子会徘徊5秒钟,直到它死亡。
这是有效的,因为父级关闭了管道的读取端。如果从父级移除close $out
,则不会触发SIGPIPE
,并且程序会无限期地打印无线。
答案 1 :(得分:2)
如果您不关闭文件,您的程序可能会用完免费文件描述符。
man perlfunc:
close
Closes the file or pipe associated with the filehandle, flushes the IO
buffers, and closes the system file descriptor.
答案 2 :(得分:1)
在文件关闭之前,某些输出错误可能会延迟。因此,关闭文件和检查返回值通常是一种好习惯。如在
# open (my $fd, ">", $fname) somewhere upstream
close $fd
or die "Couldn't finish writing to $fname: $!";
除此之外,程序将很乐意在退出时关闭全局文件句柄,并在它们离开范围时关闭它们。