Mac OS X上最大打开文件的默认限制为256(ulimit -n),我的应用程序需要大约400个文件处理程序。
我尝试使用setrlimit()更改限制,但即使函数正确执行,我仍然限制为256。
这是我使用的测试程序:
#include <stdio.h>
#include <sys/resource.h>
main()
{
struct rlimit rlp;
FILE *fp[10000];
int i;
getrlimit(RLIMIT_NOFILE, &rlp);
printf("before %d %d\n", rlp.rlim_cur, rlp.rlim_max);
rlp.rlim_cur = 10000;
setrlimit(RLIMIT_NOFILE, &rlp);
getrlimit(RLIMIT_NOFILE, &rlp);
printf("after %d %d\n", rlp.rlim_cur, rlp.rlim_max);
for(i=0;i<10000;i++) {
fp[i] = fopen("a.out", "r");
if(fp[i]==0) { printf("failed after %d\n", i); break; }
}
}
,输出为:
before 256 -1
after 10000 -1
failed after 253
我不能要求使用我的应用程序的人在/ etc文件或其他内容中查找。我需要应用程序自己完成它。
答案 0 :(得分:5)
rlp.rlim_cur = 10000;
两件事。
第一。大声笑。显然你在Mac OS X'stdio中发现了一个错误。如果我修改你的程序/添加错误处理/等,并用open()系统调用替换fopen(),我可以很容易地达到10000的限制(比我的10.6.3'OPEN_MAX限制10240低240 fds)
第二。 RTFM:man setrlimit
。必须特别针对OPEN_MAX处理最大打开文件的情况。
答案 1 :(得分:5)
etresoft在apple discussion board上找到答案:
这里的问题是你的 printf()函数。你打电话的时候 printf(),你正在初始化 内部数据结构到一定程度 尺寸。然后,你调用setrlimit()来 尝试调整这些尺寸。那 函数失败,因为你有 已经在使用那些内部 结构与您的printf()。如果你 使用两个rlimit结构(一个用于 之前和之后),不要 打印它们直到打电话 setrlimit,你会发现你可以 改变当前的极限 甚至在命令行中处理 程序。最大值为10240。
答案 2 :(得分:2)
这可能是您的libc的一个严格限制。某些版本的solaris具有类似的限制,因为它们将fd
存储为unsigned char
结构中的FILE
。如果你的libc也是这种情况,你可能无法做你想做的事。
据我所知,setrlimit
之类的内容只会影响您可以使用open
打开的文件数量(fopen几乎肯定会在open
上实现)。因此,如果此限制在libc级别上,则需要备用解决方案。
当然,您始终无法使用fopen
,而是使用几乎所有unix版本上的open
系统调用。
缺点是您必须使用write
和read
而不是fwrite
和fread
,这些都不会执行缓冲等操作(这些都是在您的libc,而不是操作系统本身)。所以它最终可能成为性能瓶颈。
你能描述一下需要同时打开400个文件**的场景吗?我并不是说没有必要的情况。但是,如果您更清楚地描述您的用例,那么也许我们可以推荐更好的解决方案。
答案 3 :(得分:2)
出于某种原因(可能是二进制兼容性),您必须在包含_DARWIN_UNLIMITED_STREAMS
之前定义<stdio.h>
:
#define _DARWIN_UNLIMITED_STREAMS
#include <stdio.h>
#include <sys/resource.h>
main()
{
struct rlimit rlp;
FILE *fp[10000];
int i;
getrlimit(RLIMIT_NOFILE, &rlp);
printf("before %d %d\n", rlp.rlim_cur, rlp.rlim_max);
rlp.rlim_cur = 10000;
setrlimit(RLIMIT_NOFILE, &rlp);
getrlimit(RLIMIT_NOFILE, &rlp);
printf("after %d %d\n", rlp.rlim_cur, rlp.rlim_max);
for(i=0;i<10000;i++) {
fp[i] = fopen("a.out", "r");
if(fp[i]==0) { printf("failed after %d\n", i); break; }
}
}
打印
before 256 -1
after 10000 -1
failed after 9997
此功能似乎已在Mac OS X 10.6中引入。
答案 4 :(得分:0)
我知道这听起来很愚蠢,但你真的需要同时打开400个文件吗? 顺便说一下,你是否以root身份运行这段代码?
答案 5 :(得分:-1)
Mac OS不允许我们像许多基于unix的操作系统那样轻松更改限制。我们必须创建两个文件
/Library/LaunchDaemons/limit.maxfiles.plist /Library/LaunchDaemons/limit.maxproc.plist 描述最大proc和max文件限制。文件的所有权需要更改为&#39; root:wheel&#39;
仅此一项并不能解决问题,默认情况下,最新版本的mac OSX使用&#csrutil&#39;,我们需要禁用它。要禁用它,我们需要在恢复模式下重启我们的mac,并从那里使用终端禁用csrutil。
现在,我们可以轻松地从终端本身轻松更改最大打开文件句柄限制(即使在正常启动模式下)。
以下链接详细说明了此方法。 http://blog.dekstroza.io/ulimit-shenanigans-on-osx-el-capitan/
适用于OSX-elcapitan和OSX-Seirra。