Linux中文件句柄泄露

句柄|文件描述符

文件描述符,File Descriptor,简称FD。文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。socket返回的也是文件描述符。值得注意的是,文件描述符是一个整数,它和指针不是一回事,但是他们之间可以通过一些函数进行转换。

在Linux系列的操作系统上,由于Linux的设计思想便是把一切设备都视作文件。因此,文件描述符为在该系列平台上进行设备相关的编程实际上提供了一个统一的方法。

特别需要注意的是,在Windows平台下,将文件描述符、信号量以及互斥锁等等内核对象都记做句柄handle,因此这里说的Linux下的句柄泄漏并不靠谱,应该是Linux下的文件描述符泄漏,在Windows平台下才叫句柄泄漏。

文件句柄泄露

在Linux中,如果一个文件正在被某个进程占用,用户操作rm删除该文件后,我们ls后发现文件已经不存在了,但实际上该文件仍然在磁盘上。直到使用它的进程退出后,文件占用的磁盘空间才会被释放。

这是因为,在Linux中,每个文件都有2个计数器,i_count和i_nlink。i_count表示文件正在被调用的数量。i_nlink表示硬链接的数量。可以理解为i_count为内存的引用计数器,i_nlink为磁盘的引用计数器。当一个文件被某一个进程引用时,对应i_count数就会增加;当创建文件的硬链接的时候,对应i_nlink数就会增加。rm操作是将文件的i_nlink减少了,如果没有其它的硬链接i_nlink就为0了;但由于该文件依然被进程引用,因此,此时文件对应的i_count并不为0,所以即使执行rm操作,但系统并没有真正删除这个文件,当只有i_nlink及i_count都为0的时候,这个文件才会真正被删除。也就是说,还需要解除该进程的对该文件的调用才行。

因此,在这种情况下,就需要使用lsof工具来查看文件被哪些进程的占用情况了。