2010-07-02 32 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

相關問題