在子进程中关闭已打开的文件描述符

问题描述:

是否有一种方法可以遍历已打开的文件描述符(由父进程打开)并在子进程中逐个关闭它们?在子进程中关闭已打开的文件描述符

操作系统: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

下面的语句的情况并不少见(这是从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

就我所知,在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