Linux文件描述符

时间:2015-09-01 13:10:05

标签: linux system

我有一个Java程序,平均运行2周后会卡住并产生以下错误:

Caused by: java.net.SocketException: Too many open files
        at sun.nio.ch.Net.socket0(Native Method)
        at sun.nio.ch.Net.socket(Net.java:415)
        at sun.nio.ch.Net.socket(Net.java:408)
        at sun.nio.ch.SocketChannelImpl.<init>(SocketChannelImpl.java:105)

这告诉我许多插座已打开但从未关闭。 在深入研究程序设备之前,我开始检查我可以从linux本身获取哪些信息。我正在使用Redhat。

然后,提出了几个问题如下:

  1. 为什么以下命令不能提供相同的输出?
  2. [ec2-user@ip-172-22-28-102 ~]$ sudo ls /proc/32085/fd | wc -l
    592
    [ec2-user@ip-172-22-28-102 ~]$ sudo lsof -a -p 32085 | wc -l 
    655
    
    1. 有没有办法从proc stat info中知道哪个线程创建了哪个文件描述符?
    2. 似乎没有,因为如果我执行以下操作,我会得到相同的信息:

      [ec2-user@ip-172-22-28-102 ~]$ sudo ls /proc/32085/task/22386/fd | wc -l
      592
      [ec2-user@ip-172-22-28-102 ~]$ sudo ls /proc/32085/fd | wc -l
      592
      

      如果我直接从/ proc /下面转到该线程。

      THX

3 个答案:

答案 0 :(得分:5)

  

有没有办法从proc stat info中知道哪个线程创建了哪个文件描述符?

我很确定这里的答案是“不”。文件描述符由进程打开,而不是线程(并且对于由同一进程生成的所有线程都可见)。

  

为什么以下命令不能提供相同的输出?

首先,-a的{​​{1}}参数在这种情况下似乎是无操作。具体而言,该男子称其“使列表选择选项成为AND,如上所述”。所以你真的只是在跑步:

lsof

这将打印除打开文件描述符(例如内存映射文件,当前工作目录等)以外的内容,而sudo lsof -p 32085 仅包含打开的文件描述符。所以你得到不同的结果,因为你要求不同的信息。

答案 1 :(得分:0)

您收到该消息的唯一原因是您已打开文件,并且在使用后您没有关闭它们。您的Java应用程序中有文件描述符泄漏。 Java程序员通常不会检查内存,因为垃圾收集器会处理未引用的对象。如果保存文件描述符而不关闭某些数据结构,或者在使用后没有关闭文件,则可以达到允许进程的最大限制(这是按进程控制的,可以由{{1}更改} shell命令)

但是如果您的问题是文件描述符泄漏,那么推高ulimit只会延迟问题一段时间。必须关闭文件描述符,否则您将遇到麻烦。

答案 2 :(得分:-1)

我今天刚刚遇到这个差异,解释是lsof考虑了更多类型的文件,比如内存映射对象,运行时库等