如何增加“最大打开文件数”的限制Mac OS X 上的 C 语言
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 文件或其他文件中。我需要应用程序自己完成它。
The default limit for the max open files on Mac OS X is 256 (ulimit -n) and my application needs about 400 file handlers.
I tried to change the limit with setrlimit() but even if the function executes correctly, i'm still limited to 256.
Here is the test program I use:
#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; }
}
}
and the output is:
before 256 -1
after 10000 -1
failed after 253
I cannot ask the people who use my application to poke inside a /etc file or something. I need the application to do it by itself.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
有两件事。
第一。哈哈。显然您在 Mac OS X 的 stdio 中发现了一个错误。如果我修复你的程序/添加错误处理/等,并用 open() 系统调用替换 fopen(),我可以轻松达到 10000 的限制(比我的 10.6.3' OPEN_MAX 限制 10240 低 240 个 fd)
第二。 RTFM:
man setrlimit
。必须针对 OPEN_MAX 专门处理最大打开文件数的情况。Two things.
1st. LOL. Apparently you have found a bug in the Mac OS X' stdio. If I fix your program up/add error handling/etc and also replace fopen() with open() syscall, I can easily reach the limit of 10000 (which is 240 fds below my 10.6.3' OPEN_MAX limit 10240)
2nd. RTFM:
man setrlimit
. Case of max open files has to be treated specifically regarding OPEN_MAX.etresoft 在 Apple 讨论区上找到了答案:
etresoft found the answer on the apple discussion board:
由于某种原因(可能是二进制兼容性),您必须在包含
之前定义_DARWIN_UNLIMITED_STREAMS
:打印
此功能似乎已在 Mac OS X 10.6 中引入。
For some reason (perhaps binary compatibility), you have to define
_DARWIN_UNLIMITED_STREAMS
before including<stdio.h>
:prints
This feature appears to have been introduced in Mac OS X 10.6.
这可能是您的 libc 的硬限制。某些版本的Solaris 也有类似的限制,因为它们将
fd
作为unsigned char
存储在FILE
结构中。如果您的 libc 也是这种情况,您可能无法执行您想要的操作。据我所知,诸如
setrlimit
之类的东西只会影响您可以使用open
打开多少个文件(fopen 几乎肯定是在open
上实现的)。因此,如果此限制是在 libc 级别上,则您将需要替代解决方案。当然,您可以始终不使用
fopen
,而是使用几乎所有 UNIX 变体上都可用的open
系统调用。缺点是您必须使用
write
和read
而不是fwrite
和fread
,后者不起作用像缓冲这样的事情(这都是在你的 libc 中完成的,而不是由操作系统本身完成的)。所以它最终可能成为性能瓶颈。您能描述一下需要同时打开 400 个文件的场景吗?我并不是说没有必要这样做。但是,如果您更清楚地描述您的用例,那么也许我们可以推荐更好的解决方案。
This may be a hard limitation of your libc. Some versions of solaris have a similar limitation because they store the
fd
as anunsigned char
in theFILE
struct. If this is the case for your libc as well, you may not be able to do what you want.As far as I know, things like
setrlimit
only effect how many file you can open withopen
(fopen is almost certainly implemented in terms onopen
). So if this limitation is on the libc level, you will need an alternate solution.Of course you could always not use
fopen
and instead use theopen
system call available on just about every variant of unix.The downside is that you have to use
write
andread
instead offwrite
andfread
, which don't do things like buffering (that's all done in your libc, not by the OS itself). So it could end up be a performance bottleneck.Can you describe the scenario that requires 400 files open ** simultaneously**? I am not saying that there is no case where that is needed. But, if you describe your use case more clearly, then perhaps we can recommend a better solution.
我知道这听起来是个愚蠢的问题,但您真的需要同时打开 400 个文件吗?
顺便问一下,您是否以 root 身份运行此代码?
I know that's sound a silly question, but you really need 400 files opened at the same time?
By the way, are you running this code as root are you?
Mac 操作系统不允许我们像许多基于 UNIX 的操作系统那样轻松更改限制。我们必须创建两个文件
/Library/LaunchDaemons/limit.maxfiles.plist
/Library/LaunchDaemons/limit.maxproc.plist
描述最大进程和最大文件限制。文件的所有权需要更改为“root:wheel”,
仅此并不能解决问题,默认情况下最新版本的 mac OSX 使用“csrutil”,我们需要禁用它。要禁用它,我们需要在恢复模式下重新启动 Mac,然后使用终端禁用 csrutil。
现在我们可以轻松地从终端本身更改最大打开文件句柄限制(即使在正常启动模式下)。
此方法在以下链接中有详细解释。 http://blog.dekstroza.io/ulimit-shenanigans-on -osx-el-capitan/
适用于 OSX-elcapitan 和 OSX-Seirra。
Mac OS doesn't allow us to easily change the limit as in many of the unix based operating system. We have to create two files
/Library/LaunchDaemons/limit.maxfiles.plist
/Library/LaunchDaemons/limit.maxproc.plist
describing the max proc and max file limit. The ownership of the file need to be changed to 'root:wheel'
This alone doesn't solve the problem, by default latest version of mac OSX uses 'csrutil', we need to disable it. To disable it we need to reboot our mac in recovery mode and from there disable csrutil using terminal.
Now we can easily change the max open file handle limit easily from terminal itself (even in normal boot mode).
This method is explained in detail in the following link. http://blog.dekstroza.io/ulimit-shenanigans-on-osx-el-capitan/
works for OSX-elcapitan and OSX-Seirra.