如何增加“最大打开文件数”的限制Mac OS X 上的 C 语言

发布于 2024-09-08 00:04:34 字数 806 浏览 5 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

铁憨憨 2024-09-15 00:04:34

rlp.rlim_cur = 10000;

有两件事。

第一。哈哈。显然您在 Mac OS X 的 stdio 中发现了一个错误。如果我修复你的程序/添加错误处理/等,并用 open() 系统调用替换 fopen(),我可以轻松达到 10000 的限制(比我的 10.6.3' OPEN_MAX 限制 10240 低 240 个 fd)

第二。 RTFM:man setrlimit。必须针对 OPEN_MAX 专门处理最大打开文件数的情况。

rlp.rlim_cur = 10000;

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.

物价感观 2024-09-15 00:04:34

etresoft 在 Apple 讨论区上找到了答案:

这里的全部问题是你的
printf() 函数。当你打电话时
printf(),你正在初始化
内部数据结构一定
尺寸。然后,您调用 setrlimit() 来
尝试调整这些尺寸。那
功能失败,因为你有
已经在使用那些内部的
与 printf() 的结构。如果你
使用两个 rlimit 结构(一个用于
之前,之后一个),并且不要
打印它们直到调用后
setrlimit,你会发现可以
改变电流的限制
即使在命令行中也可以处理
程序。最大值为 10240。

etresoft found the answer on the apple discussion board:

The whole problem here is your
printf() function. When you call
printf(), you are initializing
internal data structures to a certain
size. Then, you call setrlimit() to
try to adjust those sizes. That
function fails because you have
already been using those internal
structures with your printf(). If you
use two rlimit structures (one for
before and one for after), and don't
print them until after calling
setrlimit, you will find that you can
change the limits of the current
process even in a command line
program. The maximum value is 10240.

挽手叙旧 2024-09-15 00:04:34

由于某种原因(可能是二进制兼容性),您必须在包含 之前定义 _DARWIN_UNLIMITED_STREAMS

#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 中引入。

For some reason (perhaps binary compatibility), you have to define _DARWIN_UNLIMITED_STREAMS before including <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; }
  }

}

prints

before 256 -1
after 10000 -1
failed after 9997

This feature appears to have been introduced in Mac OS X 10.6.

云淡风轻 2024-09-15 00:04:34

这可能是您的 libc 的硬限制。某些版本的Solaris 也有类似的限制,因为它们将fd 作为unsigned char 存储在FILE 结构中。如果您的 libc 也是这种情况,您可能无法执行您想要的操作。

据我所知,诸如 setrlimit 之类的东西只会影响您可以使用 open 打开多少个文件(fopen 几乎肯定是在 open 上实现的)。因此,如果此限制是在 libc 级别上,则您将需要替代解决方案。

当然,您可以始终不使用 fopen ,而是使用几乎所有 UNIX 变体上都可用的 open 系统调用。

缺点是您必须使用 writeread 而不是 fwritefread,后者不起作用像缓冲这样的事情(这都是在你的 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 an unsigned char in the FILE 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 with open (fopen is almost certainly implemented in terms on open). 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 the open system call available on just about every variant of unix.

The downside is that you have to use write and read instead of fwrite and fread, 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.

夏の忆 2024-09-15 00:04:34

我知道这听起来是个愚蠢的问题,但您真的需要同时打开 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?

雪化雨蝶 2024-09-15 00:04:34

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文