简体   繁体   English

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

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

The default limit for the max open files on Mac OS X is 256 (ulimit -n) and my application needs about 400 file handlers. Mac OS X上最大打开文件的默认限制为256(ulimit -n),我的应用程序需要大约400个文件处理程序。

I tried to change the limit with setrlimit() but even if the function executes correctly, i'm still limited to 256. 我尝试用setrlimit()更改限制,但即使函数正确执行,我仍然限制为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. 我不能要求使用我的应用程序的人在/ etc文件或其他内容中查找。 I need the application to do it by itself. 我需要应用程序自己完成它。

rlp.rlim_cur = 10000; rlp.rlim_cur = 10000;

Two things. 两件事情。

1st. 1。 LOL. 大声笑。 Apparently you have found a bug in the Mac OS X' stdio. 显然你在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) 如果我修复你的程序/添加错误处理/ etc并用open()系统调用替换fopen(),我可以很容易地达到10000的限制(比我的10.6.3'OPEN_MAX限制10240低240 fds)

2nd. 第2位。 RTFM: man setrlimit . RTFM: man setrlimit Case of max open files has to be treated specifically regarding OPEN_MAX. 最大打开文件的情况必须特别针对OPEN_MAX进行处理。

etresoft found the answer on the apple discussion board : etresoft在苹果讨论板上找到答案:

The whole problem here is your printf() function. 这里的整个问题是你的printf()函数。 When you call printf(), you are initializing internal data structures to a certain size. 当您调用printf()时,您正在将内部数据结构初始化为特定大小。 Then, you call setrlimit() to try to adjust those sizes. 然后,调用setrlimit()尝试调整这些大小。 That function fails because you have already been using those internal structures with your printf(). 该函数失败,因为您已经在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. 如果使用两个rlimit结构(一个用于before,一个用于after),并且在调用setrlimit之后不打印它们,您会发现即使在命令行程序中也可以更改当前进程的限制。 The maximum value is 10240. 最大值为10240。

For some reason (perhaps binary compatibility), you have to define _DARWIN_UNLIMITED_STREAMS before including <stdio.h> : 出于某种原因(可能是二进制兼容性),您必须在包含<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; }
  }

}

prints 版画

before 256 -1
after 10000 -1
failed after 9997

This feature appears to have been introduced in Mac OS X 10.6. 此功能似乎已在Mac OS X 10.6中引入。

This may be a hard limitation of your libc. 这可能是您的libc的一个严格限制。 Some versions of solaris have a similar limitation because they store the fd as an unsigned char in the FILE struct. 某些版本的solaris具有类似的限制,因为它们将fd存储为FILE结构中的unsigned char If this is the case for your libc as well, you may not be able to do what you want. 如果你的libc也是这种情况,你可能无法做到你想要的。

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 ). 据我所知,像setrlimit这样的东西只影响你可以用open多少文件(fopen几乎肯定是在open )。 So if this limitation is on the libc level, you will need an alternate solution. 因此,如果此限制在libc级别上,则需要备用解决方案。

Of course you could always not use fopen and instead use the open system call available on just about every variant of unix. 当然,您总是不能使用fopen ,而是使用几乎所有unix变体上的open系统调用。

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). 缺点是你必须使用writeread而不是fwritefread ,它们不会做像缓冲这样的事情(这些都是在你的libc中完成的,而不是由操作系统本身完成的)。 So it could end up be a performance bottleneck. 因此它最终可能成为性能瓶颈。

Can you describe the scenario that requires 400 files open ** simultaneously**? 你能描述一下需要同时打开400个文件**的场景吗? 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. 但是,如果您更清楚地描述您的用例,那么也许我们可以推荐更好的解决方案。

I know that's sound a silly question, but you really need 400 files opened at the same time? 我知道这听起来很愚蠢,但你真的需要同时打开400个文件吗? By the way, are you running this code as root are you? 顺便问一下,你是否以root身份运行此代码?

Mac OS doesn't allow us to easily change the limit as in many of the unix based operating system. Mac OS不允许我们像许多基于unix的操作系统那样轻松更改限制。 We have to create two files 我们必须创建两个文件

/Library/LaunchDaemons/limit.maxfiles.plist /Library/LaunchDaemons/limit.maxproc.plist describing the max proc and max file limit. /Library/LaunchDaemons/limit.maxfiles.plist /Library/LaunchDaemons/limit.maxproc.plist描述最大进程和最大文件限制。 The ownership of the file need to be changed to 'root:wheel' 文件的所有权需要更改为'root:wheel'

This alone doesn't solve the problem, by default latest version of mac OSX uses 'csrutil', we need to disable it. 仅这一点并没有解决问题,默认最新版本的mac OSX使用'csrutil',我们需要禁用它。 To disable it we need to reboot our mac in recovery mode and from there disable csrutil using terminal. 要禁用它,我们需要在恢复模式下重启我们的mac,并从那里使用终端禁用csrutil。

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/ http://blog.dekstroza.io/ulimit-shenanigans-on-osx-el-capitan/

works for OSX-elcapitan and OSX-Seirra. 适用于OSX-elcapitan和OSX-Seirra。

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

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