Всегда ли файловые дескрипторы для сокетов linux в возрастающем порядке

У меня есть сокет-сервер на C / linux. Каждый раз, когда я создаю новый сокет, ему назначается файловый дескриптор. Я хочу использовать эти FD как uniqueID для каждого клиента. Если гарантировано, что они всегда будут назначаться в возрастающем порядке (как в случае с Ubuntu, на которой я работаю), то я мог бы просто использовать их как индексы массива.

Итак, вопрос: гарантированно ли файловые дескрипторы, назначаемые из сокетов Linux, всегда находятся в порядке возрастания?


person Josh Brittain    schedule 21.02.2012    source источник


Ответы (3)


Гарантируется, что FD будут уникальными на протяжении всего срока службы сокета. Так что да, теоретически вы, вероятно, могли бы использовать FD в качестве индекса для массива клиентов. Однако я бы предостерегал от этого, по крайней мере, по паре причин:

  • Как уже было сказано, нет гарантии, что FD будут размещаться монотонно. accept () имел бы право вернуть FD с большим номером, что сделало бы ваш массив неэффективным. Столь короткий ответ на ваш вопрос: нет, они не гарантированно монотонны.

  • На вашем сервере, вероятно, будет много других открытых FD - stdin, stdout и stderr, чтобы назвать, кроме трех - так что снова ваш массив тратит место.

Я бы порекомендовал другой способ сопоставления FD с клиентами. В самом деле, если вы не собираетесь иметь дело с тысячами клиентов, поиск по списку клиентов должен подойти - на самом деле это не та операция, которую вам нужно выполнять в огромных количествах.

person richvdh    schedule 21.02.2012
comment
Кроме того, сокеты (и fds) являются ценным ресурсом, и вы должны выпускать их (т.е. close), когда они больше не нужны. Типичный процесс Linux обычно может иметь только несколько тысяч файловых дескрипторов (этот предел может быть увеличен). Если ваше приложение будет closean fd, ядро, вероятно, переназначит его позже ... так что в конечном итоге fd-s не монотонно выделяются ... - person Basile Starynkevitch; 21.02.2012
comment
Спасибо. Код сервера рассчитан на несколько тысяч пользователей. На самом деле линейный поиск невозможен. По сути, я пытаюсь эффективно решить проблему дизайна и структур данных. Мой пост об этом находится здесь stackoverflow.com/questions/9373739/ ps кто-то изменил заголовок моего сообщения на что-то глупое. - person Josh Brittain; 21.02.2012
comment
Подводя итог, мне нужно организовать пользователей в группы по 15 человек, а затем быстро определить, в какой группе находится пользователь. Единственный метод, который я могу придумать, - это двойное хеширование, сначала по идентификатору пользователя, а затем по идентификатору группы. - person Josh Brittain; 21.02.2012

Давайте посмотрим, как это работает внутри (я использую ядро ​​4.1.20). В Linux файловые дескрипторы распределяются с помощью __alloc_fd. Когда вы выполняете открытый системный вызов, вызывается do_sys_open. Эта процедура получает бесплатный файловый дескриптор из get_unused_fd_flags:

long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{ 
    ...
    fd = get_unused_fd_flags(flags);
    if (fd >= 0) {
        struct file *f = do_filp_open(dfd, tmp, &op);

get_unused_d_flags вызывает __alloc_fd, устанавливая минимальный и максимальный fd:

int get_unused_fd_flags(unsigned flags)
{
    return __alloc_fd(current->files, 0, rlimit(RLIMIT_NOFILE), flags);
}

__alloc_fd получает таблицу дескрипторов файла для процесса и получает fd как next_fd, который фактически устанавливается с момента предыдущего запуска:

int __alloc_fd(struct files_struct *files,
           unsigned start, unsigned end, unsigned flags)
{
    ...
    fd = files->next_fd;
    ...
    if (start <= files->next_fd)
        files->next_fd = fd + 1;

Итак, вы можете видеть, как файловые дескрипторы действительно монотонно растут ... до определенного момента. Когда fd достигнет максимума, __alloc_fd попытается найти наименьший неиспользуемый файловый дескриптор:

if (fd < fdt->max_fds)
    fd = find_next_zero_bit(fdt->open_fds, fdt->max_fds, fd);

На этом этапе файловые дескрипторы больше не будут монотонно расти, а вместо этого будут прыгать, пытаясь найти свободные файловые дескрипторы. После этого, если таблица заполнится, она будет расширена:

error = expand_files(files, fd);

В этот момент они снова начнут монотонно расти.

Надеюсь это поможет

person Jay Medina    schedule 05.05.2016

Не полагайтесь на монотонность файловых дескрипторов. Всегда обращайтесь к удаленной системе через пару адрес: порт.

person Ignacio Vazquez-Abrams    schedule 21.02.2012
comment
Не могли бы вы подробнее рассказать об этом? Разве FD не гарантируют уникальность? Если они не уникальны, не приведет ли это к ошибкам при ожидании ввода-вывода FD? - person Josh Brittain; 21.02.2012
comment
@Josh Brittain: Что происходит, когда кто-то переносит ваше программное обеспечение на Windows с помощью cygwin или другого уровня переноса? Имейте в виду, что это могли быть вы. Используйте хеш-таблицу, поскольку для работы fd должен быть уникальным. - person JimR; 21.02.2012
comment
Спасибо, JimR. Я думал о хэш-таблице и подумал, что это может быть лучше. Кажется, я вернулся к хешированию :) - person Josh Brittain; 21.02.2012