我在我的 OS X 机器上遇到了问题,我可以追溯到每个进程允许的打开文件的数量。如果我maxfiles
使用 的命令查看选项launchctl
(在limit
我的 OS X El Cap 机器上)
$ launchctl limit
cpu unlimited unlimited
filesize unlimited unlimited
data unlimited unlimited
stack 8388608 67104768
core 0 unlimited
rss unlimited unlimited
memlock unlimited unlimited
maxproc 709 1064
maxfiles 256 unlimited
软限制似乎为 256,硬限制为“无限制”。我想将软限制更改为类似的值2048
,并保持硬限制不变。当我看到limit
他们的论点时
$ launchctl help limit
Usage: launchctl limit [<limit-name> [<both-limits> | <soft-limit> <hard-limit>]
看来我可以为同一件事设置两个限制,或者设置软值和硬值。但是,如果我尝试设置无限制的硬限制。
$ sudo launchctl limit maxfiles 2048 unlimited
我最终得到了奇怪的值 10240
$ launchctl limit
cpu unlimited unlimited
filesize unlimited unlimited
data unlimited unlimited
stack 8388608 67104768
core 0 unlimited
rss unlimited unlimited
memlock unlimited unlimited
maxproc 709 1064
maxfiles 2048 10240
这里发生了什么?是否可以设置无限制的值?如果不是,这是命令的限制launchctl limit
,还是系统级别的限制?如果是后者,那么unlimited
报告的初始价值是什么?还是这个苹果就是苹果?
对于奖励积分——有谁知道为什么这个限制首先设置得这么低?
答案1
这是 XNU、FreeBSD、TrueOS 和 OpenBSD 的共同点。没有办法无限打开文件描述符的硬限制和软限制。不同的操作系统内核虽然在具体行为上有所不同,但根本不允许对该功能设置RLIMIT_NOFILES
限制。RLIM_INFINITY
setrlimit()
这在所有这些中都完全没有记录。
未记录的行为是数据段、堆栈段、每个用户的最大进程数以及打开文件描述符的最大数量的软限制和硬限制都受到各种sysctl
内核变量值的限制。详细信息(例如每个限制的上限到底是哪个内核变量)因操作系统而异。
- 在 XNU 上,特权进程不能将打开文件描述符限制设置为高于
kern.maxfiles
内核变量的值;非特权进程不能将打开文件描述符限制设置为高于kern.maxfilesperproc
内核变量的值。 这是代码。 - 在 FreeBSD 和 TrueOS 上,进程不能将打开文件描述符限制设置为高于
kern.maxfilesperproc
内核变量的值。 这是代码。 - 在 OpenBSD 上,进程不能将打开文件描述符限制设置为高于
kern.maxfiles
内核变量的值。 这是代码。
在所有这些中,帽子都是沉默的。这setrlimit()
调用不会返回错误。它简单地、默默地设置一个比程序请求的值更低的限制值。 (XNU 有一种“POSIX 模式”,在这种模式下,如果尝试提高柔软的超出上限的限制。但设置难的正如您所做的那样,限制像在其他操作系统上一样被默默限制。)如果程序尝试禁用限制的强制执行,则在这些操作系统上,会发生的情况是继续在操作系统级别强制执行限制上限值。
严格来说,这违反了 Single Unix 规范,该规范要求RLIM_INFINITY
并且没有规定在没有错误返回的情况下默默地不提供该行为:
RLIM_INFINITY
在成功调用时指定为任何资源限制值将setrlimit()
禁止执行该资源限制。
launchctl limit
正如手册所说,该命令只是指示launchd
进程调用setrlimit()
以设置自己的进程资源限制的一种方式。所以你看到的是launchd
过程开始对打开的文件描述符的数量有无限的硬限制,然后获得有限的限制,kern.maxfilesperproc
对打开文件描述符的数量有无限的硬限制,然后在第一次尝试时放硬打开文件描述符限制为无限制。
(在 FreeBSD/TrueOS 上也发生了同样的情况,进程 #1 开始时的打开文件描述符硬限制很高,并且进程 #1 程序显式地将硬限制重新设置为较低的有限值。)
(实际上,GNOME 终端中有一个非常令人讨厌的错误,它最终无法启动任何终端会话,如果 GNOME 终端服务器进程最初从其父进程继承的打开文件描述符硬限制恰好发生在这些操作系统上,则可能会触发该错误高于kern.maxfiles
/的当前值kern.maxfilesperproc
。 GNOME 终端作者认为未能将硬限制设置为最初读取的相同值是一个致命错误,没有考虑到 GNOME 终端同时会触发 XNU/BSD 行为,默默地降低硬限制,导致他们的代码最终试图增加它,这是失败的理由。)
10240 只是kern.maxfilesperproc
XNU 上内核变量的编译初始值。然而,它并不是相当就这么简单。在系统引导时,当处于“服务器性能模式”时,XNU 会将此变量初始化为缩放值的 75000 倍。