select () внутри бесконечного цикла использует значительно больше процессоров на виртуальной машине RHEL 4.8, чем на машине Solaris 10 - PullRequest
3 голосов
/ 12 марта 2010

У меня есть приложение-демон, написанное на C, и в настоящее время оно работает без известных проблем на компьютере с Solaris 10. Я в процессе переноса на Linux. Я должен был сделать минимальные изменения. Во время тестирования он проходит все тестовые случаи. Там нет никаких проблем с его функциональностью. Тем не менее, когда я просматриваю использование ЦП в режиме ожидания на моем компьютере Solaris, он использует около 0,03% ЦП. На виртуальной машине под управлением Red Hat Enterprise Linux 4.8 этот же процесс использует все доступные процессоры (обычно где-то в диапазоне + 90%).

Моей первой мыслью было, что с циклом событий что-то не так. Цикл обработки событий представляет собой бесконечный цикл (while(1)) с вызовом select(). Временной интервал настроен так, что timeval.tv_sec = 0 и timeval.tv_usec = 1000. Это кажется достаточно разумным для того, что делает процесс. В качестве теста я увеличил timeval.tv_sec до 1. Даже после этого я увидел ту же проблему.

Есть что-то, чего мне не хватает в том, как работает select в Linux и Unix? Или он работает по-разному с операционной системой на виртуальной машине? Или, может быть, есть еще что-то, чего мне не хватает полностью?

Еще одна вещь, я не уверен, какая версия сервера vmware используется. Это было только что обновлено около месяца назад.

Ответы [ 2 ]

5 голосов
/ 12 марта 2010

Я полагаю, что Linux возвращает оставшееся время, записывая его в параметр времени вызова select (), а Solaris - нет. Это означает, что программист, который не знает о спецификации POSIX, может не сбросить параметр времени между вызовами для выбора.

Это приведет к тому, что первый вызов будет иметь время ожидания usec 1000, а все остальные вызовы будут иметь время ожидания usec 0.

1 голос
/ 12 марта 2010

Как сказал Zan Lynx, временной интервал изменяется с помощью select в linux, поэтому перед каждым вызовом select необходимо переназначать правильное значение. Также я предлагаю проверить, находится ли какой-либо дескриптор файла в определенном состоянии (например, конец файла, одноранговое соединение закрыто ...). Возможно, портирование показывает некоторую скрытую ошибку в анализе возвращаемых значений (FD_ISSET и т. Д.). Это случилось и со мной несколько лет назад в порте цикла, управляемого выборкой: я неправильно использовал возвращаемое значение, и закрытый fd был добавлен в rd_set, что вызвало ошибку select. На старой платформе использовалось неправильное значение fd, чтобы иметь значение выше, чем maxfd, поэтому оно игнорировалось. Из-за той же ошибки программа не распознала ошибку выбора (select () == -1) и зациклилась навсегда.

Bye!

...