繁体   English   中英

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

[英]How to increase the limit of “maximum open files” in C on Mac OS X

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

rlp.rlim_cur = 10000;

两件事情。

1。 大声笑。 显然你在Mac OS X'stdio中发现了一个错误。 如果我修复你的程序/添加错误处理/ etc并用open()系统调用替换fopen(),我可以很容易地达到10000的限制(比我的10.6.3'OPEN_MAX限制10240低240 fds)

第2位。 RTFM: man setrlimit 最大打开文件的情况必须特别针对OPEN_MAX进行处理。

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

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

出于某种原因(可能是二进制兼容性),您必须在包含<stdio.h>之前定义_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中引入。

这可能是您的libc的一个严格限制。 某些版本的solaris具有类似的限制,因为它们将fd存储为FILE结构中的unsigned char 如果你的libc也是这种情况,你可能无法做到你想要的。

据我所知,像setrlimit这样的东西只影响你可以用open多少文件(fopen几乎肯定是在open )。 因此,如果此限制在libc级别上,则需要备用解决方案。

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

缺点是你必须使用writeread而不是fwritefread ,它们不会做像缓冲这样的事情(这些都是在你的libc中完成的,而不是由操作系统本身完成的)。 因此它最终可能成为性能瓶颈。

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

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

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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM