Всегда ли файловые дескрипторы для сокетов Linux находятся в возрастающем порядке - PullRequest
3 голосов
/ 21 февраля 2012

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

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

Ответы [ 3 ]

5 голосов
/ 05 мая 2016

Давайте посмотрим, как это работает внутри (я использую ядро ​​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);

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

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

3 голосов
/ 21 февраля 2012

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

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

  • Скорее всего, на вашем сервере останется множество других открытых FD - stdin, stdout и stderr, но три, так что ваш массив снова тратит пространство.

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

2 голосов
/ 21 февраля 2012

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

...