2010-07-02 84 views
5

在Mac OS X中的最大打开的文件的缺省限制是256(的ulimit -n)和我的应用程序需要大约400文件处理程序。如何增加的“最大打开文件”限用C在Mac OS X

我试图改变通过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文件或其他东西里面戳。我需要应用程序自行完成。

+0

为什么需要同时打开这么多文件? – sbooth 2010-07-02 15:19:19

+0

不是说它应该重要,而是在服务器版或OSX的桌面版上测试它吗?我可以想象,苹果人决定限制桌面应用可以打开多少个文件,因为打开许多文件通常是面向服务器的任务... – 2010-07-02 22:12:24

回答

5

etresoft发现了apple discussion board答案:

这里的整个问题是你 printf()函数。当您拨打 printf()时,您正在初始化 内部数据结构为某个 大小。然后,你调用setrlimit()到 尝试调整这些大小。 函数失败,因为您有 已经使用这些内部 结构与您的printf()。如果您 使用两个RLIMIT结构(一个用于 前一个后),也不要 打印出来,直到调用 后的setrlimit,你会发现,你可以 即使在命令改变当前 过程的极限行 程序。最大值为10240

0

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

+0

是的,我需要同时打开400个文件,并且我不是root用户。正如男人所说,因为我不改变最大限度,但仅限于限制,我不必成为根。 – acemtp 2010-07-02 15:20:47

+2

但是会不会限制最大限制? – nategoose 2010-07-02 15:36:14

5

rlp.rlim_cur = 10000;

两件事情。

1st。大声笑。显然你已经在Mac OS X的stdio中发现了一个错误。如果我修改你的程序上/添加错误处理/等,并与开放()系统调用替换fopen()函数,我可以轻松达到10000的限制(这是240个FDS我下面的10.6.3' OPEN_MAX限制10240)

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

+1

Thx为答案。 当你说它可能是mac os x上的stdio中的一个错误,或者这是个玩笑吗? 所以唯一的解决方案是使用系统调用,而不是标准的C函数? – acemtp 2010-07-02 21:43:54

+0

@acemtp:限制可能是一个更好的词。该标准只需要libc来保证你一次可以打开8个文件(包括'stdin' /'stdout' /'stderr'!)。这将是一个不寻常的限制,但没有听说过。 – 2010-07-02 22:11:23

+1

@acetemp,@evan:在Linux上安装好stdio并不会遇到任何问题。我个人会认为这是一个错误。 8个文件一次?? stdio,stdin,stderr - 3已经很忙了。应用程序日志文件+跟踪文件 - 只剩下3个免费的...如果你问我,就会有一个愚蠢的错误。 – Dummy00001 2010-07-03 08:41:43

2

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

据我所知,像setrlimit只影响你能有多少文件,open打开(FOPEN是在这些方面几乎可以肯定实现上open)。所以如果这个限制是在libc级别的,你将需要一个替代解决方案。

当然,您可以始终不使用fopen,而是使用可用于几乎每个unix变体的open系统调用。

的缺点是,你必须使用writeread,而不是fwritefread,不做事喜欢缓冲(这是在你的libc全部完成,而不是由操作系统本身)。所以它最终可能会成为性能瓶颈。

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

+0

libc限制:是的。看到我的评论。改变程序使用open()而不是fopen()修复了这个问题。在Linux btw上工作起来就像一个魅力 - 在用rlp.rlim_max代替10000这个明显的解决方法之后(但是在Mac OS X上,即使它不同于OPEN_MAX的上限也必须检查)。您需要400 fds的场景...我维护也将数据备份到磁盘的专用网络服务器。看到2K套接字和正在使用的打开文件并不少见。 – Dummy00001 2010-07-02 20:44:31

+0

@ Dummy00001:好吧,那肯定是** a **的情况,但是让acemtp描述他正在尝试做什么仍然可以帮助:-P。但看起来我们发现问题的本质。 – 2010-07-02 21:10:03

+0

感谢澄清起源。 – Dummy00001 2010-07-03 08:45:46

2

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

-1

Mac OS不允许我们轻松地更改许多基于Unix操作系统的限制。我们要创建两个文件

/Library/LaunchDaemons/limit.maxfiles.plist /Library/LaunchDaemons/limit.maxproc.plist 描述最大proc和最大文件限制。该文件的所有权需要更改为'root:wheel'

这并不能解决问题,默认情况下,最新版本的mac OSX使用'csrutil',我们需要禁用它。要禁用它,我们需要在恢复模式下重启我们的mac,并从那里禁用使用终端的csrutil。

现在我们可以轻松地从终端本身轻松更改最大打开文件句柄限制(即使在正常启动模式下)。

这种方法在下面的链接中有详细的解释。 http://blog.dekstroza.io/ulimit-shenanigans-on-osx-el-capitan/

适用于OSX-elcapitan和OSX-Seirra。

+0

OP询问如何以编程方式在C中执行此操作,而不是在用户级别执行此操作。 – 2017-01-17 09:33:12

相关问题