为什么我会过早达到文件数量限制?

为什么我会过早达到文件数量限制?

在我们的开发系统之一(Ubuntu 21.10 桌面)上运行的自定义应用程序因错误而崩溃socket: Too many open files。所以我立即检查了限制。这是输出:

$ ulimit -n
65535

现在这很奇怪的原因是应用程序在崩溃时仅使用 1019 个套接字。鉴于可能还有其他一些文件描述符打开,我认为它达到了 1024 的限制。

为什么桌面ulimit -n明确表示限制是 65535 却强加 1024 限制?

只是为了让这件事变得更加奇怪。我有两个应用程序。一个epoll基于网络抓取工具和一个PACKET_MMAP基于应用程序,该应用程序SYN向多个网络服务器发送消息以启动连接。该epoll应用程序不会崩溃,但使用的套接字数量远多于 1024 个。而PACKET_MMAP使用原始套接字的基础应用程序却崩溃了。

此外,在服务器(也运行 Ubuntu)上测试的相同应用程序不会崩溃。

因此,无论问题是什么,它都是特定于桌面和原始套接字应用程序的。

编辑:

cat /proc/pid/limits按要求输出:

Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             31106                31106                processes 
Max open files            1024                 1048576              files     
Max locked memory         1025802240           1025802240           bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       31106                31106                signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us  

输出显示最大打开文件的软限制实际上是 1024,这与ulimit -n.是什么赋予了?

答案1

对于不同的用户和不同的进程可以设置不同的资源限制。您ulimit显示特定用户的特定限制,但systemd有其自己的默认限制。您需要更新您的systemd程序的单元文件以设置文件限制LimitNOFILE=1048576

文档欲了解详情

答案2

这就是我用一些 C 代码解决这个问题的方法。我将以下代码行添加到我的应用程序中:

#include <sys/resource.h>

...

    struct rlimit lim;
    
    getrlimit(RLIMIT_NOFILE, &lim);
    printf("Soft: %d Hard: %d\n", (int)lim.rlim_cur, (int)lim.rlim_max);
    lim.rlim_cur = lim.rlim_max;
    
    
    if (setrlimit(RLIMIT_NOFILE, &lim) == -1) {
        printf("rlimit failed\n");
        return -1;
    }
    getrlimit(RLIMIT_NOFILE, &lim);
    printf("New Soft: %d New Hard: %d\n", (int)lim.rlim_cur, (int)lim.rlim_max);

但我仍然不知道如何通过编辑系统上的配置文件来做到这一点。然而,这个答案对于那些满足于用 C 代码解决问题的人来说仍然有用。

答案3

当您想要更改 Ubuntu Linux 中 systemd 管理的服务的限制时,您需要在 override.conf 文件中进行配置。我使用 mariadb 作为示例,但这可以推广到所有服务。

mkdir /etc/systemd/system/mariadb.service.d
vi /etc/systemd/system/mariadb.service.d/override.conf

在此文件中,您将输入以下行:

[Service]
LimitNOFILE=65535

之后,您需要重新加载单位声明

systemctl daemon-reload

并重新启动服务

systemctl restart mariadb.service

现在你将能够行政控制过程限制。 Systemd 可以使用此方法管理以下限制:

指示 ulimit 等效项 单元
限制CPU= ulimit -t 秒数
限制FSIZE= ulimit -f 字节
限制数据= ulimit -d 字节
限制堆栈= ulimit -s 字节
限制核心= ulimit -c 字节
限制RSS= ulimit-m 字节
限制NOFILE= ulimit-n 文件描述符的数量
限制AS= ulimit -v 字节
极限NPROC= ulimit -u 进程数
限制MEMLOCK= ulimit -l 字节
限制锁= ulimit-x 锁数量
限制SIGPENDING= ulimit -i 排队信号数
限制MSGQUEUE= ulimit -q 字节
限制NICE= ulimit -e 不错的水平
限制RTPRIO= ulimit -r 实时优先级
限制RTTIME= 没有同等的 微秒

来自系统文档https://www.freedesktop.org/software/systemd/man/systemd.exec.html

相关内容