За последние два дня при отладке встроенной системной среды Linux, после включения системы, при подключении Mosquitto к MQTT-серверу (EMQ) через tls, MQTT-соединение всегда блокировалось при его создании.Сейчас буду записывать отладку. процесс и шаги по решению проблемы.
Давайте сначала поговорим о среде разработки и отладки:
- Аппаратная платформа : EXP imx.6ull.
- Версия ядра : 4.1.15.
- rootfs : создан на основе buildroot
- комар : 2.0.11
- опенссл : 1.1.1
- Сервер MQTT : EMQ, поддерживающий службу TLS.
проблема внешнего вида
После загрузки системы Linux и появления приглашения на вход в оболочку вызываются mosquitto_connect и EMQ для установления соединения на основе TLS. Вызов mosquitto_connect блокируется примерно на 90 секунд, прежде чем вызов функции вернется и будет сообщено об ошибке. После этого mosquitto запустит механизм повторного подключения и снова подключится к серверу EMQ, и соединение будет успешным. В это время, если запрос на подключение к EMQ будет повторно инициирован, mosquitto_connect не будет блокироваться.
Некоторые причины первоначальных сомнений:
- После запуска системы перед инициализацией сети вызывается mosquitto_connect, и соединение с EMQ может не состояться. Попробуйте метод тестирования: улучшите процесс инициализации сети и оптимизируйте время вызова mosquitto_connect.После тестирования он недействителен.
- Если вы подозреваете, что возникла проблема с сервером EMQ, попробуйте метод проверки: используйте другие устройства для проверки инициирования подключения TLS к тому же EMQ, и проблем не будет.
- При запуске не синхронизируется системное время (1970-01-01 08:00:00).После подключения сети служба ntpd синхронизирует сетевое время с локальным, поэтому соединение mqtt будет заблокировано.После подумав об этом, если это проблема с системным временем, mosquitto_connect должен вернуть сообщение об ошибке, указывающее, что сертификат проверки TLS недействителен, а не блокируется.
- Я подозревал, что другие части приложения мешают процессу вызова mosquitto_connect. Я использовал mosquitto_pub для публикации сообщений непосредственно в EMQ и обнаружил то же явление.
После вышеописанных раундов подозрений и тестирования отладка зашла в тупик.Я был немного подавлен.Подумав об этом, я использовал козырную карту: самый глупый и эффективный метод: вставить логи отладки в процесс выполнения mosquitto_connect . На самом деле, иногда, казалось бы, самый глупый метод является наиболее эффективным методом отладки.Пока направление правильное, стоит потратить некоторое время и энергию.
Шаги отладки
Следуйте процессу вызова mosquitto_connect, добавьте журналы и определите место блокировки. Вот небольшой совет по отладке: начните с магистрали, а затем детали . То есть сначала добавьте журналы в ключевые места на основном пути, которые нужны для отладки, а затем компилировать и отлаживать.Вы можете определить общее расположение проблемы, затем снова добавить журналы в подпроцесс, скомпилировать и отладить.Таким образом, рекурсивно шаг за шагом, вы можете быстро найти проблема . Применив этот метод, я наконец определил, что проблема блокировки mosquitto_connect следующая:
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_client_method());
Позвольте мне кратко представить SSL_CTX_new, который в основном представляет собой блок управления, созданный openssl для связи TLS. Чтобы подтвердить проблему, я написал тестовую программу, чтобы еще раз подтвердить, вызвала ли эта функция проблему. код показан ниже:
#include <openssl/conf.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/ui.h>
#include <openssl/ssl.h>
void ssl_test(void)
{
printf("ssl_test:TP0.\n");
SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_client_method());
(void)ssl_ctx;
printf("ssl_test:TP1.\n");
}
Процедура очень проста: нужно просто подтвердить, является ли виновником SSL_CTX_new. После включения Linux немедленно выполняется тестовая функция. Сначала печатается «ssl_test:TP0». Примерно через 90 секунд печатается «ssl_test:TP1». Местоположение проблемы подтверждается.
проблема найдена
Если вы новичок в механизме SSL/TLS или понимаете только процесс взаимодействия SSL/TLS, немного сложно анализировать принцип реализации SSL_CTX_new.Я принадлежу к этому типу людей, поэтому отладка еще раз в беде.
Когда я был в растерянности, я обнаружил интересный феномен: я обнаружил, что терминалу нужно напечатать только одну строку:
random: nonblocking pool is initialized
SSL_CTX_new вернется. После нескольких тестов подтвердите последовательность между ними. Видно, что существует связь между инициализацией случайного значения и блокировкой SSL_CTX_new. После этого отладка прошла относительно гладко, было действительно сложно найти выход из гор и рек, а в другой деревне нас ждало блестящее будущее .
Изучив информацию, я обнаружил, что существуют следующие основные решения для случайного: неблокирующий пул инициализируется :
1. Быстрая инициализация неблокирующего пула случайных чисел Linux.
3. Быстрая инициализация неблокирующего пула случайных чисел Linux.
После анализа 1 и 3 в основном соответствуют явлению этой проблемы: можно определить, что существует проблема с случайным драйвером ядра версии 4.1.15, из-за которой случайная инициализация замедляется (90 с), когда система запускается, и во время инициализации используется SSL_CTX_new.random, которому необходимо дождаться завершения случайной инициализации, прежде чем он сможет продолжить выполнение, вызывая блокировку SSL_CTX_new и, в конечном итоге, блокировку mosquitto_connect.
Решать проблему
Измените код случайного драйвера ядра: driver/char/random.c , найдите функцию add_interrupt_randomness и измените следующий код:
Исходный код:
if ((fast_pool->count < 64) &&
!time_after(now, fast_pool->last + HZ))
return;
Модифицированный код:
if ((fast_pool->count < 64) &&
!time_after(now, fast_pool->last + HZ) &&
nonblocking_pool.initialized)
return;
Примечание: Версия ядра в этой статье — 4.1.15. После проверки кода ядра было обнаружено, что в более новой версии ядра ошибка устранена!
Скомпилируйте, замените ядро и после тестирования проблема решена!
постскриптум
Оглядываясь назад на процесс решения этой проблемы, я не знаю, заметили ли вы это. Вначале явление проблемы и первопричину проблемы можно описать как «восемь полюсов невозможно поразить » . раз я чувствую, что проблема вот-вот будет решена, в конце концов, это все равно. Чувство потери и тревоги будет становиться все сильнее и сильнее . На самом деле, проанализировав процесс решения проблемы постфактум, нетрудно найти ключ к решению проблемы : сначала сохраняйте спокойствие и определите направление, затем используйте научные методы, чтобы неуклонно двигаться вперед, верьте в себя, и, наконец, проблема в конечном итоге будет решена. Это всего лишь вопрос времени .