СУБД ЛИНТЕР и ReactOS, технические детали

Во многом благодаря активности фонда ReactOS не будет большой ошибкой предположить, что любой постоянный читатель Хабра слышал о весьма амбициозном проекте «свободного Виндоуcа». Я не стал исключением, и еще в ходе работ по созданию системы сборки для СУБД ЛИНТЕР идея включить поддержку этой операционной системы меня посещала не раз. Совсем недавно ее удалось воплотить в жизнь.

2ce24af91e4d4d4399b3bfca4dbfae32.jpg

Под катом вас ждут технические детали работ, включая опыт развертывания ReactOS на реальном железе, и немного моего субъективного мнения об этом проекте.


Начало было обнадеживающим — инсталляция Windows дистрибутива ЛИНТЕР на ReactOS проходила успешно: службы корректно регистрировались, базы создавались, сервер на первый взгляд работал исправно. Однако, первый же функциональный тест ни дал никакого результата. Никакого в прямом смысле этого слова — клиент находил локальное ядро СУБД, пытался установить соединение, однако сервер никак не реагировал на эти попытки. Было очевидно, что проблема связана с IPC. ЛИНТЕР поддерживает несколько механизмов межпроцессного взаимодействия: локальные сокеты, разделяемую память, mailslot, но именно последние как раз и были способом коммуникации тестов с ядром по умолчанию. После повторной конфигурации и пересборки тестов с использованием разделяемой памяти удалось подтвердить свое предположение — проблема заключалась в реализации mailslot под ReactOS, а при детальном исследовании удалось найти и причину: вызов функции CreateMailslot с параметром lReadTimeout = MAILSLOT_WAIT_FOREVER приводил к немедленному возврату с кодом ошибки ERROR_SEM_TIMEOUT:

hMailslotClient = CreateMailslot(LMS, 0L, MAILSLOT_WAIT_FOREVER, (LPSECURITY_ATTRIBUTES) NULL);
if (hMailslotClient == INVALID_HANDLE_VALUE)
{
    dbgError(GetLastError(),__LINE__);
    return 1;
}

Полный пример доступен по ссылке.

Был заведен соответствующий багрепорт, исправили который достаточно оперативно. Как оказалось, значение MAILSLOT_WAIT_FOREVER (-1LL) передавалось без проверки в качестве параметра timeout в функцию KeWaitForSingleObject, что являлось ошибкой, поскольку последняя оперирует не милисекундами, а сотнями наносекунд, отрицательные значения интерпретируются как относительный таймаут, а положительные — как абсолютный, т. е. до исправления этой ошибки MAILSLOT_WAIT_FOREVER для ReactOS равнялся 100 наносекундам.
Отчет работы патчбота доступен по ссылке.


Проблема с таймаутами оказалась не единственной проблемой в реализации mailslot — практически сразу после начала коммуникации клиентского приложения с ядром поисходили deadlock-и слота. Начав искать причину я обнаружил, что драйвер mailslot file system (msfs.sys) в реализации ReactOS не поддерживает асинхронное чтение из слота:

 if (!ReadFile(hMailslotClient, lpszBuffer, LENMSG, &cbRead, &stOverlapped))
    {
        //ERROR_IO_PENDING (997) is not a failure!!
        dbgError(GetLastError(),__LINE__);

        _tprintf(TEXT("starting writer...\n"));
        startWriter();

        if (!GetOverlappedResult( hMailslotClient, &stOverlapped, &cbTr, TRUE))
        {
            dbgError(GetLastError(),__LINE__);
            return 1;
        }
    }

Полный пример доступен по ссылке.

Новый багрепорт уже не был так стремительно закрыт, что и понятно, учитывая объем исправлений. Поэтому я решил посодействовать доработке драйвера, хотя, признаюсь, последний раз драйвер для Windows писал в студенческие времена.
Мои доработки msfs.sys сводились к обработке IRP пакетов с помощью Cancel-Safe IRP очередей, что позволило организовать асинхронное чтение из слота. Не самый изящный вариант, однако достаточно простой и надежный. Правки были добавлены в коммите 69475, после чего удалось успешно «прогнать» все функциональные тесты ядра ЛИНТЕР.
Отчет работы патчбота доступен по ссылке.


Последние найденные мной ошибки в ReactOS изначально «всплыли» в виде артефактов в строках графических интерфейсаов средств администрирования ЛИНТЕР. Все эти приложения построены на базе нашей кросплатформенной UI библиотеки — RelAPI. Как выяснилось, самые безобидные баги оказались проявлением самых серьезных ошибок в ReactOS: функций mbstowcs и wcstombs не обрабатывали должным образом ситуации, когда первые параметом был NULL:

char rosStr[BUFFER_SIZE] = "Reactos";
cnt = mbstowcs(NULL,rosStr,BUFFER_SIZE);

wchar_t rosStr[BUFFER_SIZE] = L"Reactos";
cnt = wcstombs(NULL,rosStr,BUFFER_SIZE);

Полный пример доступен по ссылке.

Соответствующий багрепорт был достаточно оперативно закрыт, что позволило довести испытания работы нашего продукта под управлением ReactOS до конца.
Отчет работы патчбота доступен по ссылке.


В обсуждении ReactOS часто проскакивают вопросы в духе «а работает ли эта ОС на реальном современном железе?» — в моем случае ответ утвердительный: да работает, но не без проблем. Первая из них заключалась в неработоспособности ehci контроллера, usb клавиатура и мышь, успешно эмулировались BIOS-ом как legacy и работали, но ровно до тех пор пока драйвер usbehci.sys не резетил контроллер, поэтому пришлось от него (драйвера) отказаться, со всеми вытекающими последствиями в виде неработающих USB устройств. Второй проблемой оказалась нестабильная работа ОС, которая периодически «падала» в BSOD в hdaudbus.sys (драйвер шины для High Definition Audio). Эту проблему удалось решить отключив соответствующий контроллер в настройках BIOS.
После всех произведенных манипуляций система под управлением ReactOS (билд 20151025-r69700) работала стабильно и позволяла «прогнать» все необходимые тесты и замеры производительности.

Все эксперименты проводились на оборудовании:

pechenkin@big:~$ lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation 2nd Generation Core Processor Family DRAM Controller [8086:0100] (rev 09)
00:01.0 PCI bridge [0604]: Intel Corporation Xeon E3–1200/2nd Generation Core Processor Family PCI Express Root Port [8086:0101] (rev 09)
00:16.0 Communication controller [0780]: Intel Corporation 6 Series/C200 Series Chipset Family MEI Controller #1 [8086:1c3a] (rev 04)
00:1a.0 USB controller [0c03]: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #2 [8086:1c2d] (rev 05)
00:1c. 0 PCI bridge [0604]: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 1 [8086:1c10] (rev b5)
00:1c. 3 PCI bridge [0604]: Intel Corporation 82801 PCI Bridge [8086:244e] (rev b5)
00:1c. 4 PCI bridge [0604]: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 5 [8086:1c18] (rev b5)
00:1c. 5 PCI bridge [0604]: Intel Corporation 6 Series/C200 Series Chipset Family PCI Express Root Port 6 [8086:1c1a] (rev b5)
00:1d.0 USB controller [0c03]: Intel Corporation 6 Series/C200 Series Chipset Family USB Enhanced Host Controller #1 [8086:1c26] (rev 05)
00:1f.0 ISA bridge [0601]: Intel Corporation Z68 Express Chipset Family LPC Controller [8086:1c44] (rev 05)
00:1f.2 SATA controller [0106]: Intel Corporation 6 Series/C200 Series Chipset Family SATA AHCI Controller [8086:1c02] (rev 05)
00:1f.3 SMBus [0c05]: Intel Corporation 6 Series/C200 Series Chipset Family SMBus Controller [8086:1c22] (rev 05)
01:00.0 VGA compatible controller [0300]: NVIDIA Corporation GF104 [GeForce GTX 460] [10de:0e22] (rev a1)
01:00.1 Audio device [0403]: NVIDIA Corporation GF104 High Definition Audio Controller [10de:0beb] (rev a1)
03:00.0 PCI bridge [0604]: Integrated Technology Express, Inc. Device [1283:8892] (rev 10)
05:00.0 USB controller [0c03]: Etron Technology, Inc. EJ168 USB 3.0 Host Controller [1b6f:7023] (rev 01)
06:00.0 USB controller [0c03]: Etron Technology, Inc. EJ168 USB 3.0 Host Controller [1b6f:7023] (rev 01)


Результат работы теста TPC-B на ReactOS для fat32, размер пула ЛИНТЕРа — 390 Мб.:

Mode     = PESSIMISTIC 
Accounts = 1000
....
Transactions:       817600 
Working time:       299 seconds 
Speed = 2727.333 tps

Результат работы теста TPC-B на Windows 7, fat32, размер пула ЛИНТЕРа — 390 Мб.:

Mode     = PESSIMISTIC 
Accounts = 1000
....
Transactions:       688400 
Working time:       299 seconds 
Speed = 2298.881 tps 


ReactOS находится сейчас в состоянии альфа, о чем честно сообщает официальный сайт проекта и не пригодна к использованию в продакшне, однако у меня сложилось впечатление, что в случае необходимости ОС в приемлемые сроки можно довести «до ума» для работы на конкретном оборудовании с ограниченным набором программного обеспечения. Коме того, считаю, что для любителей «завести» железо или покопаться во внутренностях ОС этот проект, вне всякого сомнения будет интересен. Отдельно стоит отметить доброжелательность сообщества ReactOS и его ориентированность на достижение результата.

© Habrahabr.ru