ISSN 2305-5626. Вестник МГТУ им. Н.Э. Баумана: электронное издание. 2013
2
сетевых сокетов. Блокировка рабочего потока приведет к прекраще-
нию обработки всех соединений, за которые был ответственен забло-
кированный поток, на неопределенное время. В худшем случае это
время зависит от поведения клиента сетевой службы.
Таким образом, проверка корректности является актуальной про-
блемой, но известные существующие средства анализа программного
обеспечения (ПО) не имеют специализированных функций для поис-
ка таких ошибок. В работе приведено описание разработки метода
проверки корректности реализации мультиплексированного сетевого
ввода-вывода в сетевых службах. Программная реализация созданно-
го метода состоит из загружаемого модуля для модифицированного
ядра ОС, анализирующего системные вызовы ввода-вывода и выпол-
няющего разработанные алгоритмы поиска ошибок, и прикладной
программы, взаимодействующей с пользователем.
Ошибки при реализации мультиплексирования соединений.
Стандарт POSIX.1-2008 определяет три системных вызова мульти-
плексирования для опроса сокетов на предмет возможности неблоки-
рующих операций чтения или записи:
select( )
,
poll( )
,
pselect( )
[3]. При описании метода для краткости под
select( )
будем понимать любой возможный системный вызов мультиплекси-
рования, под
read( )
— любую возможную функцию чтения из со-
кета, а под
write( )
— любую возможную функцию записи в сокет
из ограниченных стандартом POSIX.1-2008.
Известные ошибки мультиплексирования можно подразделить на
две группы (рис. 1): критические и некритические. Критические
ошибки могут заблокировать поток на сколь угодно длительное вре-
мя, зависящее от действий клиентской стороны. Последствиями не-
критических ошибок являются задержки в обслуживании клиентов,
но сам рабочий поток не блокируется на неопределенное время.
Под ошибкой блокированием потока или процесса до чтения из
готового сокета (см. рис. 1) понимается наличие операции, проводи-
мой на сервере, которая вызывает кратковременное «засыпание»
процесса. Примером такой операции может служить необходимость
чтения из локального файла.
Чтение из одного и того же сокета в различных рабочих потоках
приводит к тому, что нельзя гарантировать неблокирующий характер
чтения: когда данные в сокете появятся, несколько потоков присту-
пят к их чтению, но успешно выполнить эту операцию в общем слу-
чае может только один поток. Остальные потоки в состоянии сна бу-
дут ожидать прихода новых данных от клиента, при этом
обслуживаемые ими соединения обрабатываться не будут.
Примером ошибки, приводящей к блокирующему чтению, может
служить последовательность вызовов
select( ) — read(fd) — . .
. — read(fd)
, где
fd
— дескриптор сокета, о котором вызов
select( )
сообщил как о готовом для чтения. Первое чтение будет
неблокирующим, но про второе этого сказать в общем случае нельзя.