от Vladsun(2-10-2008)

рейтинг (24)   [ добре ]  [ зле ]

Printer Friendly Вариант за отпечатване



Проблемът

Преди време на един от сърверите се появи проблем - машината "забиваше" абсолютно случайно във времето и единствено хардуерно рестартиране я оправяше. Нямаше нищо по логовете и естествено решихме, че проблемът е хардуерен. След няколко замени на различни компоненти от компютърната конфигурация се оказа, че дънната платка е дефектирала.

Вероятността подобно нещо да се случи и при вас е достатъчно голяма. Още повече, че по закона на Мърфи, точно тогава ще сте примерно на море :). От друга страна са и неприятностите, които може да ви създаде такава машина до отстраняване на проблема.

Проблеми от подобно естество се решават чрез използване на така наречените watchdog устройства.

По същество те представляват таймери, чиито изходи са свързани с входа за рестартиране на отделна система в компютърната конфигурация. В някои случаи се рестартира цялата конфигурация. Рестартирането се предизвиква само, ако таймерът е достигнал предварително зададено време. Ако хардуерът и софтуерът работят нормално, то специално написан софтуер нулира таймера през интервал по-малък от гореспоменатия и съответно рестартиране не се предизвиква. В случай, че се появи някакъв хардуерен или софтуерен дефект, то изпълнението на софтуера за нулиране на таймера става невъзможно, таймерът достига критичното време и се предизвиква рестартиране.

Устройства от този тип се продават на пазара в много разновидности (прим. за PCI слот). Факт е обаче, че първо, те са относително скъпи и второ - няма ги на българския пазар. Поради тези причини си направих сам watchdog.

Хардуерът

Устройството се включва към паралелния порт на сървера, а изходът му към рестарт бутона на сървера. Използва +5V захранване от сървера. Връзката между паралелния порт и входа на устройството се осъществява през оптрон, т.е. имаме галванично разделяне.

Схемата на устройството е доста проста:



Използван е класически таймер 555, характеризиращ се с високо ниво на стабилност на генерираните времеви интервали, както и ниска чувствителност към промяна на захранващото напрежение. В случая таймерът е свързан в автогенераторен режим. Изходът му е контактната група на релето - нормално отворена.

Резисторите R2 и R3 определят двете времена на генерираните импулси - импулса и паузата. По принцип двете времена за установен генераторен режим на краче 3 са:

T(0) = 0.693*R3*C1
T(1) = 0.693*(R2 + R3)*C1

В нашия случай тези времена трябва да се коригират, тъй като при нормална работа на схемата тя де факто е в моногенераторен режим и винаги се генерира само първия импулс от поредицата. Тогава времето T(1) е 1.6 пъти по-голямо:

Т(1) = 1.1*(R2 + R3)*C1

За избраните в схемата стойности на R2, R2 и C1 тези времена са:

T(0) = 1.4 sec
T(1) = 200 sec

Това означава, че софтуерът, който нулира таймерът трябва да генерира импулси най-малко на всеки 200 sec. Поради наличието на толеранси на елементите е необходимо да се вземе поне с 20% по-къс интервал. Ако таймерът достигне критичното време от 200 секунди, то релето се задейства за 1.4 секунди. В схемата могат да се използват всякакви транзистори, оптрони и диоди с общо предназначение.

Устройството може да се свърже към всеки избран от вас изход на паралелния порт (ето как). В моя случай съм избрал D0 - съответно крачета 2(+) и 18(0V). Краче 2 е свързано към горния на схемата вход, а краче 18 на долния.

Софтуерът

С малки поправки и компилации от намерени в Интернет сорсове, сътворих следното:

pport.c
#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <asm/io.h>
 
 #define base 0x278           /* printer port base address */
 
 main(int argc, char **argv)
 {
         int value, sleepval;
         
         if (argc!=3)
         {
                 fprintf(stderr, "Usage:\n pport portmask portdelay \n"); exit(1);
         }
         if (sscanf(argv[1],"%i",&value)!=1)
         {
                 fprintf(stderr, "Error: Parameter 1 is not a number.\n"); exit(1);
         }
         if (sscanf(argv[2],"%i",&sleepval)!=1)
         {
                 fprintf(stderr, "Error: Parameter 2 is not a number.\n"); exit(1);
         }
         if ((value<0) || (value>255))
         {
                 fprintf(stderr, "Error: Invalid numeric value. The port mask must be between 0 and 255\n"); exit(1);
         }
         if ((sleepval<0) || (sleepval>255))
         {
                 fprintf(stderr, "Error: Invalid numeric value. The delay value must be between 0 and 255\n"); exit(1);
         }
         if (ioperm(base,1,1))
         {
                 fprintf(stderr, "Error: Couldn't get the port at %x\n", base); exit(1);
         }
         
         outb((unsigned char)value, base);
         if (sleepval != 0)
         {
                 usleep(sleepval*1000000);
                 outb(0, base);
         }
 }


Преди всичко трябва да се обърне внимание на адреса 0x278 - той може да е различен за вашата конфигурация. Проверете в BIOS-a какви стойности са зададени за адреса на паралелния порт и заменете адреса в сорса преди компилиране.

Компилирането се извършва по обичайния начин:
pport
gcc -o /usr/local/sbin/pport pport.c


Програмата изисква два параметъра - побитова маска за порта и време за задържане на стойността преди автоматично нулиране. В нашия случай маската е 1 (само изход D0) и избираме време 2 секунди за принудително нулиране на таймера. Тогава командният ред е:

pport
pport 1 2


Втората програмка, която е нужна за да се завърши напълно системата трябва да се пуска при стартиране на машината и да се изпълнява горния команден ред на всеки 160 секунди. Това при мен (Slackware) е реализирано по следния начин:

/usr/local/sbin/hwdog
#!/bin/bash
 while [ 1 ]
 do
 /usr/local/sbin/pport 1 2
 sleep 160
 done


а в /etc/rc.d/rc.local добавям:

rc.local
/usr/local/sbin/hwdog &


Съществуват и варианти при които извикването на pport да се прави вътрешно от някой от критичните за сървера процеси.

Е, това е! Дано съм помогнал на някой :)


<< Как да си направим система за споделяне на видео файлове | Инсталиране на Beryl под Mandriva Linux 2007 >>