以下成语并不少见(取自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);
}
}
这是一种 hack(正如 MIMEDefang 代码所承认的那样)。在许多情况下,从 FD 3(或STDERR_FILENO+1)而不是 0 开始会更有用。close() 返回带有无效 FD 的 EBADF,但这通常不会出现问题(至少在 C 中不会,在其他语言可能会引发异常)。
由于您可以使用getrlimit(RLIMIT_NOFILE,...) 确定文件描述符上限,即defined:
RLIMIT_NOFILE
这是一个大于系统可以分配给新创建的描述符的最大值的数字。如果超过此限制,分配文件描述符的函数将失败,并将 errno 设置为 [EMFILE]。这个限制限制了进程可以分配的文件描述符的数量。
你可以使用这个(减去 1)作为循环的上限。
以上和ulimit -n、getconf OPEN_MAX和sysconf(OPEN_MAX)应该都同意。
由于open()总是分配最低的空闲FD,所以最大打开文件数和最高的FD+1是同一个数。
要确定哪些 fds 是打开的,而不是 close() 使用无操作 lseek(fd, 0, SEEK_CUR) 如果 fd 未打开,它将返回 EBADF(调用 lseek() 以获取条件 @987654338 没有明显的好处@ 尽管)。 socat 的 filan 循环超过 0 .. FD_SETSIZE 调用 fstat()/fstat64()。
守护任意进程的libslack daemon utility 也使用这种蛮力方法(同时确保在inetd 下使用时保持前三个描述符打开)。
如果您的程序可以跟踪文件句柄,最好这样做,或者在可用的情况下使用FD_CLOEXEC。但是,如果您希望进行防御性编码,您可能更愿意不信任您的父进程,例如由浏览器启动的外部处理程序/查看器进程,例如像这样long-lived and ancient Mozilla bug 在 Unix 平台上。
对于偏执狂(您是否希望您的 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 "$@"