2013-03-07 205 views
3

是否有一種方法可以遍歷已打開的文件描述符(由父進程打開)並在子進程中逐個關閉它們?在子進程中關閉已打開的文件描述符

操作系統:Unix。

關閉原因:RLIMIT_NOFILE限制setrlimit()限制進程可能分配的文件描述符的數量。如果我們想通過設置此限制來限制我們的子進程,則它取決於已經分配的文件描述符。

試圖設置在一個子進程這個限制被限制爲父進程有一些打開的文件描述符,因此我們不能設置這個限制比這個數字少。例如:如果父進程分配了10個文件描述符,並且我們希望限制子進程文件描述符的數量小於10(說3),則需要在子進程內關閉7個文件描述符。

這個問題的解決可以惠及所有那些誰想要限制從創建新文件或打開新的網絡連接的子進程。

+0

*「如果父進程已分配10個文件描述符... 「*:」分配「對你來說意味着什麼?因爲文件描述符是打開或關閉的。單詞分配與內存管理相關聯... – thkala 2013-03-07 09:12:00

+0

更正:我打算說10父進程的打開文件描述符,感謝您的糾正thkala – learner 2013-03-07 10:19:51

回答

3

下面的語句的情況並不少見(這是從MIMEDefang的C部分,採取):

/* Number of file descriptors to close when forking */ 
#define CLOSEFDS 256 
... 

static void 
closefiles(void) 
{ 
    int i; 
    for (i=0; i<CLOSEFDS; i++) { 
     (void) close(i); 
    } 
} 

它是一個黑客的東西(如MIMEDefang代碼諱言)。在許多情況下這是更加有用在FD 3(或STDERR_FILENO+1)開始而不是0 close()返回EBADF具有無效FD,但是這通常不存在問題(至少不是在C,在其他語言的可能會引發異常)。

由於可以判斷文件描述符上限與getrlimit(RLIMIT_NOFILE,...)這是defined爲:

RLIMIT_NOFILE

這是比最大值大的頭號,該系統可以分配給新創建的描述符。如果超出此限制,則分配文件描述符的函數將失敗,並將errno設置爲[EMFILE]。此限制限制了進程可能分配的文件描述符的數量。

您可以使用此(減1)作爲循環的上限。 以上和ulimit -n,getconf OPEN_MAXsysconf(OPEN_MAX)應該都是同意的。

由於open()總是分配最低的空閒FD,所以打開的文件的最大數量和最高的FD + 1是相同的數字。

該守護任意進程的libslack daemon utility也使用這種方法(同時確保在inetd下使用前三個描述符時保持打開狀態)。

在您的程序可以跟蹤文件句柄的情況下,最好這樣做,或者在可用的情況下使用FD_CLOEXEC。然而,如果你想防守編碼,你可能更喜歡不信任你的父進程,比如當啓動由瀏覽器啓動的外部處理程序/查看器進程時,比如說。像Unix上的這個 12 15 year old Mozilla bug一樣。

對於偏執狂(你希望自己的PDF閱讀器,以繼承每個打開的Firefox FD包括緩存,然後打開的TCP連接):

#!/bin/bash 
# you might want to use the value of "ulimit -n" instead of picking 255 
for ((fd=3; fd<=255; fd++)); do 
    exec {fd}<&- # close 
done 
exec /usr/local/bin/xpdf "[email protected]" 
+0

非常豐富的答案。 – Grodriguez 2014-08-13 07:50:22

0

就我所知,在Unix/POSIX中沒有通用方法來遍歷打開的文件描述符。處理所描述問題的傳統方法是在自己的代碼中跟蹤它們,如果需要使用數組結構(如數組或列表),並在fork()之後但在exec()之前關閉子進程。

一些操作系統,然而,提供了一個潛在的解決方案,如果你正在創建子進程後調用exec()。通過setting the FD_CLOEXEC flag for a file descriptor using fcntl()O_CLOEXEC標誌爲open(),操作系統被指示在調用exec()之前關閉該特定文件描述符。您將必須查閱目標操作系統的文檔,以確定是否支持這些標誌以及哪些標誌受支持。

+0

我可以通過文件描述符數字從0循環到MAX允許的文件描述符,並基於呼叫在dup(int fildes)函數的輸出上?由於dup()失敗,返回'-1'。 這是一種糟糕的方式,或者它是另一種瞭解我正在尋找的信息的原始方式? – learner 2013-03-12 04:35:36

+0

@ user2136293:在您的提案中有很多假設可以並會破壞您的代碼:1.您認爲您可以可靠地找出最大的FD號碼。除了MAX_INT之外,沒有其他可靠的限制。你假設這個數字是「合理的」。你打算探測2^31 FD嗎? 3.你假設你可以盲目地關閉()任何你不喜歡的文件描述符。如果您的某個圖書館由於某些特定原因而保持開放的FD,該怎麼辦? – thkala 2013-03-13 13:12:45

+0

@ user2136293:你究竟在做什麼? [你真正的問題是什麼?](http://mywiki.wooledge.org/XyProblem) – thkala 2013-03-13 13:13:43

相關問題