不关闭Perl中的目录句柄会有什么影响?

Bri*_*anH 6 perl syntax-error

我最近继承了其他人编写的一些代码.

我发现代码中的任何地方都打开了一个目录以供阅读,它从未被关闭,因为原始开发人员有语法问题 - 他正在使用该close函数尝试关闭目录句柄而不是closedir函数.

代码是这样的:

opendir( DIR, $dir ) or die "Cannot open $dir: $!\n";
@files = readdir( DIR );
close( DIR );
Run Code Online (Sandbox Code Playgroud)

(这是Perl最佳实践(第208,278页)中关于检查close函数返回的另一个好点.如果close在这种情况下检查了返回,那么它将失败并显示"Bad file number".)

我已经改变了这一点closedir,但它让我开始疑惑:由于目录句柄从未关闭,对于保持目录句柄长时间打开有什么负面影响?

该程序较大(3,500行代码),运行一段时间(5-10分钟),并且该程序的多个实例同时运行.对于上面示例中的此目录,$dir所有实例的值都相同.如果此程序的10个实例同时运行,则它们都会对同一目录保持一个打开的目录句柄5分钟或更长时间.我确信Perl会在程序结束时自动关闭目录句柄,但最佳做法是尽快关闭它.

对我来说更明显的是,打开文件句柄会导致问题(特别是对于可以写入的文件句柄),但是如果不关闭目录句柄会发生什么坏事?

我问的原因是因为有一个奇怪的情况,这个程序试图创建一个文件(在上面的$ dir定义的目录中).文件名中嵌入了PID,因此文件可能已存在的可能性较小,但Perl无法打开文件进行写入,因为它说它已经存在.当我们查看目录时,该文件不存在.我想知道这个目录下的所有打开目录句柄是否都会导致这样的问题?

我不确定操作系统是否有所作为,但该程序在AIX上运行.

提前谢谢,周五快乐!

Jon*_*ler 11

你浪费了一个目录描述符 - 它可能算作文件描述符.如果您的程序打开了足够的目录以用完文件描述符,那么最终会对您造成伤害.否则,它是非常无害的,虽然不太理想.它使系统(和Per​​l)保持其本可以释放的资源.

如果目录句柄是局部变量,而不是普通的DIR样式名称,那么您可能会在后面清理Perl.见opendir说:

打开名为EXPR的目录,以便由readdir,telldir,seekdir,rewinddir和closedir进行处理.如果成功则返回true.DIRHANDLE可以是一个表达式,其值可以用作间接dirhandle,通常是真正的dirhandle名称.如果DIRHANDLE是未定义的标量变量(或数组或散列元素),则会为变量分配对新匿名目标的引用.DIRHANDLEs有自己的命名空间与FILEHANDLEs分开.

  • @mobrule - 对不起,由于没有可用的文件描述符,我无法发表你的评论 - 真诚的,StackOverflow Solaris后端.... (8认同)

raf*_*afl 8

不会有任何严重后果.内核本身的内存使用量会略有增加,内核本身无法释放内部使用的迭代器来循环遍历目录条目列表,也可能来自perl端.

另外,只要目录的任何描述符仍然打开,就无法从文件系统中实际删除数据.如果某个其他外部进程将删除您拥有句柄的目录,它将停止出现在将来的目录列表中,但数据仍然必须保留在磁盘上,并且仍然可以通过打开的句柄进程访问.例如,这可能导致磁盘使用中的奇数.

另请注意,您不一定要手动关闭所有手柄.使用词法文件句柄时,只要对句柄的最后一次引用消失,就会自动关闭:

 { # new scope
     opendir(my $handle, ...) or ...;
     ...
 } # implicit closedir happens here
Run Code Online (Sandbox Code Playgroud)


Eth*_*her 7

这是一个总是使用词法文件(和目录)句柄的课程 - 词法句柄在超出范围时会自动关闭.

所以你只是浪费描述符(如Jonathan所描述的),如果1.你使用了旧式的glob句柄,或者2.所有代码都在一个没有子程序或其他作用域的平面脚本中.使用良好的编程实践和无意的错误将更少:)