Следующая идиома не редкость (взята из части C MIMEDefang):
/* 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,...)
, который определен как:
RLIMIT_NOFILE
Это число на единицу больше максимального значения, которое система может присвоить вновь созданному дескриптору. Если этот предел превышен, функции, которые выделяют файловый дескриптор, должны завершиться ошибкой с errno, установленным в [EMFILE]. Этот предел ограничивает количество файловых дескрипторов, которые может выделить процесс.
вы можете использовать это (вычитая 1) как верхний предел цикла. Все вышеизложенное и ulimit -n
, getconf OPEN_MAX
и sysconf(OPEN_MAX)
должны согласиться.
Поскольку open()
всегда назначает самый низкий свободный FD, максимальное количество открытых файлов и самый высокий FD + 1 - это одно и то же число.
Чтобы определить, какие fd открыты, вместо close()
используйте no-op lseek(fd, 0, SEEK_CUR)
, который вернет EBADF
, если fd не открыт (хотя нет очевидной выгоды от вызова lseek()
для условного close()
). filan
socat
проходит через 0 .. FD_SETSIZE
вызывает _18 _ / _ 19_.
libslack daemon
утилита, которая демонизирует произвольные процессы, также использует этот метод грубой силы (при этом убедитесь, что три дескриптора открываются при использовании под inetd
).
В случае, если ваша программа может отслеживать дескрипторы файлов, предпочтительнее это сделать или использовать FD_CLOEXEC
, где это возможно. Однако, если вы хотите использовать защитный код, вы можете предпочесть не доверять своему родительскому процессу, например, для процесса внешнего обработчика / средства просмотра, запущенного браузером, например как эта давняя и древняя ошибка Mozilla на платформах 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 "$@"
person
mr.spuratic
schedule
01.04.2014