在我们的开发系统之一(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