【问题标题】:Linux File descriptorsLinux 文件描述符
【发布时间】:2015-09-01 13:10:04
【问题描述】:

我有一个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. 为什么以下命令没有给出相同的输出?

[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 信息中知道哪个线程创建了哪个文件描述符?

似乎没有,因为如果我执行以下操作,我会得到相同的信息:

[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/ 下进入线程,则相同。

谢谢

【问题讨论】:

    标签: linux system


    【解决方案1】:

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

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

    为什么以下命令没有给出相同的输出?

    首先,lsof-a 参数在这种情况下似乎是空操作。具体来说,该男子说它“导致列表选择选项被与,如上所述”。所以你真的只是在跑步:

    sudo lsof -p 32085
    

    这将打印打开文件描述符以外的内容(例如内存映射文件、当前工作目录等),而/proc/&lt;PID&gt;/fd 仅包含打开文件描述符。因此,您会得到不同的结果,因为您要求的信息不同。

    【讨论】:

    • 谢谢。你知道一种方法来识别进程中打开最多文件描述符的线程吗?
    • 除了检测你的代码来跟踪这类事情之外,我不知道有什么方法可以做到这一点。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 2012-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-12
        相关资源
        最近更新 更多