6

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 文件或其他内容。我需要应用程序自行完成。

4

6 回答 6

5

rlp.rlim_cur = 10000;

两件事情。

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

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

于 2010-07-02T20:14:32.997 回答
5

etresoft 在苹果讨论板上找到了答案:

这里的整个问题是你的 printf() 函数。当您调用 printf() 时,您正在将内部数据结构初始化为特定大小。然后,您调用 setrlimit() 来尝试调整这些大小。该函数失败是因为您已经在 printf() 中使用了这些内部结构。如果使用两个 rlimit 结构(一个用于 before 和一个用于 after),并且在调用 setrlimit 之后才打印它们,您会发现即使在命令行程序中也可以更改当前进程的限制。最大值为 10240。

于 2010-07-09T15:25:09.873 回答
3

出于某种原因(可能是二进制兼容性),您必须_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 中引入。

于 2014-08-18T17:42:24.907 回答
2

这可能是您的 libc 的硬限制。某些版本的 solaris 具有类似的限制,因为它们将 存储fd为结构体unsigned charFILE如果你的 libc 也是这种情况,你可能无法做你想做的事。

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

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

缺点是你必须使用writeandread而不是fwriteand fread,它不做缓冲之类的事情(这一切都在你的 libc 中完成,而不是由操作系统本身完成)。所以它最终可能成为性能瓶颈。

您能否描述需要同时**打开 400 个文件** 的场景?我并不是说没有必要这样做。但是,如果您更清楚地描述您的用例,那么也许我们可以推荐一个更好的解决方案。

于 2010-07-02T20:20:15.817 回答
0

我知道这听起来是个愚蠢的问题,但你真的需要同时打开 400 个文件吗?顺便说一句,您是否以 root 身份运行此代码?

于 2010-07-02T15:17:17.673 回答
-1

Mac OS 不允许我们像许多基于 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。

于 2017-01-17T09:27:11.963 回答