Raspberry Pi. Поднимаем Watchdog

При встраивании Raspberry Pi, в отличии от устройств на МК есть два «тонких момента»:

  1. RPi имеет операционную систему;
  2. Операционная система может зависнуть.

В случае, если на RPi построена система, допустим, мониторинга какого-либо процесса, любое зависание ОС приведет к неприятным последствиям. А теперь на минуту представим, что железка стоит за 3000 км от вас и по SSH вы уже не можете к ней подключиться. Поэтому необходима система автоматической проверки состояния системы и ее перезагрузки в случае, если произошло зависание RPi. Этим и занимается watchdog, или по-русски «сторожевой таймер». Важно заметить, что нельзя застраховаться от всех возможных причин зависания, т.к. кроме программных сбоев могут произойти сбои из-за внешней среды — перегрев, нестабильное питание, электромагнитные помехи, и т.д. Так что «надо обезопаситься и застраховаться. Вдруг что, а тут тебе на, компенсация» (c) Ноггано =))

Исходная точка:

  1. Raspberry Pi (версия не важна);
  2. Raspbian Debian Wheezy Version: January 2014 Release date: 2014-01-07.

Начнем, пожалуй, с теории.

ТЕОРИЯ

Сторожевой таймер, watchdog timer или просто watchdog — аппаратная (железка), программная (программа, скрипт, часть программы) или программно-аппаратная (железка, управляемая программно) схема контроля за зависанием системы (операционной системы, GSM-модема, банкомата, роутера или чего-то еще). Представляет из себя таймер, который необходимо периодически сбрасывать контролируемой системой; если контролируемая система не сбрасывает watchdog в течении определенного времени, то происходит ее перезагрузка. В некоторых случаях сторожевой таймер может посылать системе сигнал на перезагрузку («мягкая» перезагрузка, soft reset), в других же — перезагрузка происходит аппаратно (например, подачей нуля на ножку RST микроконтроллера; это т.н. hard reset).

С железной точки зрения, watchdog — это таймер, работающий в режиме прямого счета до определенного значения, которое может задаваться как программно, так и железно, в зависимости от его реализации. Можно обратиться по этой ссылке и посмотреть в картинках, что это значит. Зачастую, применительно к микроконтроллерам, если сторожевой таймер не используется по прямому назначению, его можно использовать как обычный таймер.

Логика работы сторожевого таймера такова:

  1. Запуск контролируемой системы;
  2. Инициализация watchdog’а. В случае, если данный таймер программно-аппаратный, указываем период сброса (допустим, 1 секунда);
  3. Если watchdog каждую секунду принимает сигнал сброса от контролируемой системы (в виде подачи какого-либо уровня на ножку МК, записи в файл, передачи параметров программе), то система работает в штатном режиме;
  4. Если watchdog не принял сигнал сброса в течении более, чем 1 секунда, посредством сигнала о том, что «все очень плохо» он перезагружает контролируемую систему (soft reset, hard reset).

Более просто — представим себе сторожевой таймер реальным злым сторожевым псом. Если ему каждый час (период сброса) кидать кость (сигнал сброса), то он молчит. Но если более чем час не кидать ему кость, он может начать громко лаять и рычать (формирование сигнала о неправильной работе системы, зависании).

В англоязычных источниках можно чаще можно встретить выражение не «кинуть кость» — «throw a bone», еще вариант «кормить собаку» — «feeding the dog», а «пнуть собаку» — «kick the dog». Я так понимаю, это вопрос воспитания =))

ПРОГРАММНЫЙ WATCHDOG. СКРИПТ АВТОРЕКОННЕКТА WIFI

К примеру, программный watchdog для программы — это кусок кода, работающий параллельно и контролирующий основную программу.

Хорошим примером сторожевого таймера может являться следующий пример — если вы конфигурируете подключение к сети Raspberry Pi без сторонних менеджеров, то есть через /etc/network/interfaces, встает следующая проблема — нет автоматического реконнекта при дропе. Решено это может быть программным сторожевым таймером — скриптом на Python 2.x, приведенном ниже.

#!/bin/python
#network_watchdog.py - script for autoreconnect WiFi
import os
import time
DELAY = 30 # delay in seconds
while True:
    time.sleep(DELAY)
    if os.system("ping google.com -c 1") != 0:
        print "Connection loss. Reconnecting"
        os.system("sudo ifup --force wlan0")

Для запуска в фоновом режиме:

$ sudo python network_watchdog.py &

Для прерывания работы скрипта сначала вернуть его из фонового режиме командой.

$ fg

и завершить его работу нажатием Ctrl+C.

Вариант на тему — скрипт, взятый отсюда:

#!/bin/bash
#network_watchdog.sh
while true ; do
    if ifconfig wlan0 | grep -q "inet addr:" ; then
        sleep 60
    else
        echo "Network connection down! Attempting reconnection."
        ifup --force wlan0
        sleep 10
    fi
done

Запуск:

$ sudo ./network_watchdog.sh &

Прерывание работы аналогично скрипту на Python. Если вам не нравится то, что скрипты имеют бесконечные циклы, можно почитать

$ man crontab

АППАРАТНЫЙ WATCHDOG

Чисто аппаратный сторожевой таймер представляет из себя отдельную схему, выполненную как на дискретных компонентах, так и в виде микросхемы. Одним из хороших примеров, может являться микросхема от Maxim Integrated MAX6323/24, схема включения которой показана на рисунке ниже.

maxim_watchdog

Как нам говорит даташит и опыт, выход RESET — отрытый сток, в случае, если необходимо сбросить контролируемую микросхему, то данный выход сажается на землю, на RESET контролируемой микрухи подается 0 и выполняется hard reset.

Спектр применения таких микросхем — устройства промышленной, медицинской и автомобильной электроники, где необходима высокая надежность работы устройства.

ПРОГРАММНО-АППАРАТНЫЙ WATCHDOG

Watchdog превратился в современном понимании в программно-аппаратную реализацию. То есть, теперь watchdog — это встроенный, допустим, в микроконтроллер, управляемый регистрами таймер, формирующий сигнал сброса в случае, если кость ему не кидать в определенный период. Таким образом, в отличие от железного сторожевого таймера, программно-аппаратный имеет настройки, которые задают его поведение. Например, на msp430 это делается так. Также, если микросхема, которую мы хотим контролировать, не имеет встроенного сторожевого таймера, он может быть реализован на внешнем микроконтроллере (рекурсия — у которого тоже есть сторожевой таймер) с соответствующей прошивкой. Ну вот — на лицо и железка, и возможность конфигурации.

Таким образом, программно-аппаратный wathcdog может быть:

  1. Частью микроконтроллера, системы-на-кристалле;
  2. Внешним устройством, выполненном на микроконтроллере.

В Raspberry Pi он именно программно-аппаратный.

ПОДНИМАЕМ WATCHDOG НА RASPBERRY PI

Используемая в Raspberri Pi система-на-кристалле (SoC — System on Crystal) BCM2835 имеет встроенный сторожевой таймер, который умеет считать до 15 секунд.

Для его работы необходимо загрузить модуль в ядро:

$ sudo modprobe bcm2708_wdog
$ sudo sh -c "echo 'bcm2708_wdog' >> /etc/modules"

Кроме этого, необходимо добавить в начало файла /etc/init.d/mathkernel следующие строки:

#!/bin/sh
### BEGIN INIT INFO
# Provides: mathkernel
# Required-Start: $syslog
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: mathkernel
# Description: This file should be used to construct scripts to be
# placed in /etc/init.d.
### END INIT INFO
#
# rest of file here

Далее, как и во всем мире Linux, есть два подхода — заморочиться и делать на самом низком уровне абстракции или воспользоваться готовым. Остановимся на втором варианте, а первый оставим для желающих позаниматься самостоятельно=))

Конечно же, уже есть готовый watchdog daemon. Установим его и chkconfig

$ sudo apt-get install watchdog chkconfig

После установки включим в автозагрузку watchdog и запустим его:

$ sudo chkconfig watchdog on
$ sudo service watchdog start

Далее отредактируем /etc/watchdog.conf

$ sudo nano /etc/watchdog.conf

путем раскомментирования строчки watchdog-device = /dev/watchdog, тем самым указав точку монтирования сторожевого таймера демону. Для того, чтобы watchdog срабатывал и в тех случаях, когда список ожидающих выполнения процессов зашкаливает (говорит нам о том, что идет сильно не так), раскомментируем строчку max-load-1 = 24. тем самым мы говорим таймеру, что «если load average за минуту превысит 24, то watchdog должен перезагрузить операционку»

Также укажем параметры загрузки в ядро:


echo "options bcm2708_wdog nowayout=1 heartbeat=13" | sudo tee /etc/modprobe.d/watchdog.conf

тем самым указывая параметры:

  • nowayout=1, данный параметр устанавливает, что watchdog не может быть остановлен другими программами, если он уже запущен;
  • heartbeat=13, где 13 — это время сброса в секундах. То есть не кинули кость за 13 секунд — получай резет.

Перезапустим Raspberry:

$ sudo reboot

После перезагрузки если выполнить команду dmesg | grep watchdog, получим такой вывод:

pi@raspberrypi~ $ dmesg | grep watchdog
[ 16.012628] bcm2708 watchdog, heartbeat=13 sec (nowayout=1)?

На этом watchdog появился и в вашем Raspberry Pi. Остался один вопрос — а как проверить его работу?!

FORK-БОМБА
Чтобы посмотреть на сторожевой таймер в боевых условиях применим известный подход — Fork-Bomb (советую полностью прочитать и усвоить материал).

Для этого возьмем стандартную реализацию форк-бомбы на Питоне:

#/bin/python
#fork_bomb.py

import os

while True:
os.fork()

и запуcтим:

$ python fork_bomb.py

Система будет перезагружена через какое-то время. При форк-бомбах желательно отключить своп (в описанном примере это необязательно):

$ sudo swapoff -a

УБИВАЕМ WATCHDOG ЧЕРЕЗ kill -9

Кроме описанной форк-бомбы, можно проверить работу нашего сторожевого таймера посредством команды

$ sudo kill -9 $(pidof watchdog)

РЕЗЮМЕ

Вот таким вот нехитрым образом мы подняли сторожевой таймер и обезопасили нашу железку от возможной неработоспособности в течении длительного времени. Конечно, статья не охватила все — остался не рассмотрен hard reset по превышению температуры, минимальному количеству свободной памяти и т.д — да и таковая цель не преследовалась. Для дальнейшего изучения данной темы могу порекомендовать полезные ссылки (см. ниже) и гугл.

ПОЛЕЗНЫЕ ССЫЛКИ

Сохранить

4 комментария for “Raspberry Pi. Поднимаем Watchdog”

Олег

says:

А не пробовал юзать дога с проверкой файла? У меня он странно себя ведёт. Можно указать файл и максимальное время для проверки его модификации. Запускаю свою софтину, которая раз в 20 сек делает touch файлу. Если вотчдог запустить после софтины вручника то всё нормально, но если при загрузке ОС, то хер. Причём софтина стартует как демон и самой первой строчкой в main делает touch файлу, а дог запускается после старта всех остальных демонов. Тем не менее иногда это приводит к циклическим перезагрузкам будто софтина запущена позже дога и он видит что в файл никто давно не гадил и ребутит систему. Но по логам всё в порядке с очерёдностью запуска. Глянул в исходники watchdog и слегка офигел от main на 100500 строк, кароче лень стало копаться в нём.

says:

Нет, так не пробововал и в голову такое пока не приходило=))

А файловая система — журналируемая?! Т.е. ты уверен, что изменения по touch вносятся ровно тогда, когда ты делаешь этот вызов, в метаданные файла?

Добавить комментарий