Почему операционные системы ограничивают файловые дескрипторы? - PullRequest
17 голосов
/ 23 июля 2011

Я задаю этот вопрос после того, как изо всех сил стараюсь найти лучший способ реализации сервера очереди сообщений. Почему операционные системы ограничивают число дескрипторов открытых файлов, которые может иметь процесс и глобальная система? Моя текущая реализация сервера использует zeromq и открывает сокет подписчика для каждого подключенного клиента websocket. Очевидно, что этот единственный процесс сможет обрабатывать клиентов только до предела fds. Когда я изучаю эту тему, я нахожу много информации о том, как поднять системные ограничения до уровней, достигающих 64 Кбит / с, но никогда не упоминается, как это влияет на производительность системы и почему она равна 1 Кб и ниже для начала? Мой текущий подход состоит в том, чтобы попытаться отправить сообщения всем клиентам, используя сопрограмму в своем собственном цикле и карту всех клиентов и их каналов подписки. Но мне бы очень хотелось услышать четкий ответ об ограничениях файловых дескрипторов и о том, как они влияют на приложения, которые пытаются использовать их на уровне клиента с постоянными соединениями?

Ответы [ 4 ]

13 голосов
/ 23 июля 2011

Это может быть потому, что значение дескриптора файла является индексом в таблице дескрипторов файла.Следовательно, количество возможных файловых дескрипторов будет определять размер таблицы.Обычные пользователи не хотят, чтобы половина их оперативной памяти использовалась таблицей дескрипторов файлов, которая может обрабатывать миллионы дескрипторов файлов, которые им никогда не понадобятся.

4 голосов
/ 23 июля 2011

В целях производительности таблица открытых файлов должна быть статически размещена, поэтому ее размер должен быть фиксированным. Файловые дескрипторы просто смещаются в эту таблицу, поэтому все записи должны быть смежными. Вы можете изменить размер таблицы, но для этого необходимо остановить все потоки в процессе и выделить новый блок памяти для файловой таблицы, а затем скопировать все записи из старой таблицы в новую. Это не то, что вы хотите делать динамически, особенно когда причина, по которой вы это делаете, в том, что старая таблица заполнена!

3 голосов
/ 23 июля 2011

Существуют определенные операции, которые замедляются, когда у вас есть много потенциальных файловых дескрипторов. Одним из примеров является операция «закрыть все файловые дескрипторы, кроме stdin, stdout и stderr» - единственный переносимый * способ сделать это - попытаться закрыть все возможные файловые дескрипторы, кроме тех трех, которые могут стать медленная операция, если вы потенциально можете открыть миллионы файловых дескрипторов.

*: Если вы хотите быть непереносимым, вы можете заглянуть в /proc/self/fd - но это не главное.

Это не особенно веская причина, но это причина. Другая причина заключается в том, чтобы просто не допустить ошибок в работе программы (т. Е. Программы, которая «пропускает» файловые дескрипторы) слишком много системных ресурсов.

0 голосов
/ 09 сентября 2014

В системах Unix идиома создания процесса fork () и fork () / exec () требует итерации по всем потенциальным дескрипторам файла процесса, пытающимся закрыть каждый, обычно оставляя только несколько файловых дескрипторов, таких как stdin, stdout,stderr не тронут или перенаправлен куда-либо еще.

Так как является API Unix для запуска процесса, его необходимо выполнять каждый раз, когда создается новый процесс, включая выполнение каждого и не встроенного-in команда вызывается в сценариях оболочки.

Другие факторы, которые следует учитывать, - это то, что, хотя некоторые программы могут использовать sysconf(OPEN_MAX) для динамического определения количества файлов, которые могут быть открыты процессом, много программного обеспечения.по-прежнему использует библиотеку C по умолчанию FD_SETSIZE, которая обычно составляет 1024 дескриптора, и поэтому никогда не может иметь больше, чем столько открытых файлов, независимо от какого-либо административно определенного верхнего предела.

Unix имеет устаревший асинхронный IМеханизм ввода / вывода на основе наборов файловых дескрипторов, которые используют смещения битовпредставлять файлы для ожидания и файлы, которые готовы или находятся в состоянии исключения.Он не очень хорошо масштабируется для тысяч файлов, так как эти наборы дескрипторов необходимо настраивать и очищать каждый раз вокруг цикла выполнения.Более новые нестандартные API-интерфейсы появились в основных вариантах Unix, включая kqueue() на * BSD и epoll() на Linux для устранения недостатков производительности при работе с большим количеством дескрипторов.

Важно отметить, что select()/poll() все еще используется ОЧЕНЬ большим количеством программного обеспечения, поскольку долгое время он был API POSIX для асинхронного ввода-вывода.Современный подход асинхронного ввода-вывода POSIX теперь API aio_*, но он, вероятно, не конкурирует с API kqueue() или epoll().Я не использовал aio в гневе, и у него, конечно, не было бы производительности и семантики, предлагаемых нативными подходами, так как они могут объединять несколько событий для повышения производительности.kqueue () в * BSD имеет действительно хорошую семантику, инициируемую фронтами для уведомления о событиях, что позволяет ему заменять select () / poll (), не вызывая больших структурных изменений в вашем приложении.Linux epoll () следует примеру * BSD kqueue () и улучшает его, что, в свою очередь, следует примеру Sun / Solaris evports.

В результате увеличение количества разрешенных открытых файлов в системе добавляетзатраты времени и пространства для каждого процесса в системе, даже если они не могут использовать эти дескрипторы в зависимости от используемых ими API.Существуют также общие ограничения системы для количества разрешенных открытых файлов.Этот более старый, но интересный сводный список настроек для одновременных соединений 100–200 тыс., Использующих nginx во FreeBSD , дает некоторое представление о накладных расходах на поддержание открытых соединений и , другой охватывает более широкий диапазон систем , но «только»"видя соединения 10K как Mt Everest.

Вероятно, лучшим справочным материалом для программирования в Unix-системах является W. Richard Stevens Расширенное программирование в среде Unix

...