在Perl中不关闭目录句柄意味着什么?
我最近继承了一些别人写的代码 我发现,在代码中打开目录以供读取的任何地方,都没有关闭目录,因为原始开发人员有语法问题-他使用在Perl中不关闭目录句柄意味着什么?,perl,syntax-error,Perl,Syntax Error,我最近继承了一些别人写的代码 我发现,在代码中打开目录以供读取的任何地方,都没有关闭目录,因为原始开发人员有语法问题-他使用close函数尝试关闭目录句柄,而不是closedir函数 代码是这样的: opendir( DIR, $dir ) or die "Cannot open $dir: $!\n"; @files = readdir( DIR ); close( DIR ); (这是Perl最佳实践(第208278页)中关于检查close函数的返回的另一个好观点。如果在这种情况下检查cl
close
函数尝试关闭目录句柄,而不是closedir
函数
代码是这样的:
opendir( DIR, $dir ) or die "Cannot open $dir: $!\n";
@files = readdir( DIR );
close( DIR );
(这是Perl最佳实践(第208278页)中关于检查close
函数的返回的另一个好观点。如果在这种情况下检查close
的返回,它将失败,并显示“错误的文件号”。)
后来我将其更改为closedir
,但这让我开始思考:既然目录句柄从未关闭,那么长时间打开目录句柄会带来什么负面影响
该程序较大(3500行代码),运行一段时间(5-10分钟),并且该程序的多个实例同时运行。对于上面示例中的此目录,$dir
对于所有实例都是相同的值。如果此程序的10个实例同时运行,则它们都对同一目录持有一个开放目录句柄5分钟或更长时间。我确信Perl会在程序完成时自动关闭目录句柄,但最佳实践是尽快关闭它
对我来说,更明显的是,如果文件句柄保持打开状态会导致问题(特别是对于为写入而打开的文件句柄),但是如果不关闭目录句柄,会发生什么不好的事情呢
我问这个问题的原因是因为有一个奇怪的情况,这个程序试图创建一个文件(在上面$dir定义的目录中)。文件名中嵌入了PID,因此文件可能已经存在的可能性较小,但Perl无法打开文件进行编写,因为它说文件已经存在。当我们查看目录时,该文件不存在。我想知道这个目录上的所有开放目录句柄是否都会导致这样的问题
我不确定操作系统是否起作用,但这个程序正在AIX上运行
提前谢谢,星期五快乐 您浪费了一个目录描述符—它可能被算作文件描述符。如果您的程序打开了足够多的目录以耗尽文件描述符,那么最终会对您造成伤害。否则,它是相当无害的,虽然不太理想。它使系统(和Perl)保留资源,否则它可能会释放这些资源 如果目录句柄是一个局部变量,而不是一个普通的DIR样式名称,那么您可能需要Perl来清理它。看哪个说: 打开名为EXPR的目录,以供readdir、telldir、seekdir、rewinddir和closedir处理。如果成功,则返回true。DIRHANDLE可以是一个表达式,其值可以用作间接DIRHANDLE,通常是真正的DIRHANDLE名称。如果DIRHANDLE是未定义的标量变量(或数组或散列元素),则会为该变量分配一个对新匿名DIRHANDLE的引用。DIRHANDLEs有自己的名称空间,与FILEHANDLEs分开
不会有任何严重的后果。从内核本身来看,内存使用会略微增加,内核本身无法释放内部用于循环遍历目录项列表的迭代器,可能还会从perl端释放内存 另外,只要目录的任何描述符仍然打开,就不能从文件系统中实际删除数据。如果其他外部进程将删除您拥有句柄的目录,它将不再出现在未来的目录列表中,但数据仍必须保留在磁盘上,并且仍然可以通过打开句柄的进程访问。例如,这可能会导致磁盘使用率出现奇数 还请注意,您不必手动关闭所有句柄。使用词法文件句柄时,一旦对句柄的最后一次引用消失,就会自动关闭:
{ # new scope
opendir(my $handle, ...) or ...;
...
} # implicit closedir happens here
这是一堂始终使用词法文件(和目录)句柄的课——词法句柄在超出范围时会自动关闭
所以,如果1,那么您只会浪费描述符(正如Jonathan所描述的)。您使用了老式的球形手柄,或2。所有代码都在一个平面脚本中,没有子例程或其他作用域。使用良好的编程实践,意外错误会更少:)即使在今天,一些操作系统对文件描述符也相当吝啬(我正在看你,solaris,你的默认设置是64-256)。@mobrule-很抱歉,我不能发表你的评论,因为没有可用的文件描述符-真诚地,StackOverflow Solaris后端…此opendir位于主目录中,因此它是全局范围的。。。但是你绝对正确-良好的编程实践肯定会减少无意中的错误!根据你的代码,你使用了一个裸字句柄。除非您显式地将它们本地化,否则它们始终是全局范围的。