以下成语并不少见(取自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-2.78 开始的,实现在以后的版本中略有改变。)
这有点像 hack(正如 MIMEDefang 代码自由承认的那样)。STDERR_FILENO+1
在许多情况下,从 FD 3(或)开始而不是 0 会更有用。close()
返回EBADF
无效的 FD,但这通常不会出现问题(至少在 C 中不会,在其他语言中可能会引发异常)。
由于您可以确定文件描述符上限,getrlimit(RLIMIT_NOFILE,...)
其定义为:
RLIMIT_NOFILE
这是一个大于系统可以分配给新创建的描述符的最大值的数字。如果超出此限制,分配文件描述符的函数将失败,并将 errno 设置为 [EMFILE]。此限制限制了进程可以分配的文件描述符的数量。
您可以使用它(减去 1)作为循环的上限。上面的和ulimit -n
,getconf OPEN_MAX
和sysconf(OPEN_MAX)
应该都同意。
由于open()
总是分配最低的空闲FD,所以打开文件的最大数量和最高的FD+1是同一个数。
要确定哪些 fd 是打开的,而不是使用如果 fd 未打开则返回close()
的 no-op (虽然调用条件没有明显的好处)。的循环超过 0 ..调用/ 。lseek(fd, 0, SEEK_CUR)
EBADF
lseek()
close()
socat
filan
FD_SETSIZE
fstat()
fstat64()
守护任意进程的libslackdaemon
实用程序也使用这种蛮力方法(同时确保在使用时保持前三个描述符打开inetd
)。
在您的程序可以跟踪文件句柄的情况下,最好这样做,或者FD_CLOEXEC
在可用的情况下使用。但是,如果您希望进行防御性编码,您可能更愿意不信任您的父进程,例如由浏览器启动的外部处理程序/查看器进程,例如 Unix 平台上这个长期存在且古老的 Mozilla 错误。
对于偏执狂(您是否希望您的 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 "$@"
15 年后更新此问题已在 Firefox 58 (2018) 中解决,当时进程创建从 Netscape Portable Runtime (NSPR) API 更改为使用 LaunchApp。