Watchdog Kullanımı

Watchdog mekanizmaları, çalışan ana yazılımların beklenmedik bir şekilde sonlanması sonrasında sistemin yeniden başlatılabilmesine imkan tanır.

Bu mekanizma genellikle donanım tabanlı bir zamanlayıcı (Watchdog Timer - WDT) ile gerçekleştirilir.

Sistemin genel çalışma prensibi oldukça basittir:

  • WDT zamanlayıcısını örnek olarak 60 saniye için başlat
  • 60 saniyelik süre bitmeden hayatta olduğunu ispat et ve yeni bir 60 saniye kazan

Periyodik olarak zamanlayıcıya hayatta olduğunuzu söylediğiniz müddetçe sorun olmayacaktır. Ancak bu işlemi yapamaz hale gelirseniz (uygulamanız bir SEGFAULT ile sonlanmışsa vb.) zamanlayıcının süresi dolduğunda sistem otomatik olarak yeniden başlatılacaktır.

Buradaki yeniden başlatma işlemi kontrollü (reboot) değil, reset şeklindedir.

Kernel Panic Sistemi İle Fark

Watchdog haricinde görece benzer bir işlevi Linux çekirdeği içerisindeki panic handler ile de yapabildiğimizi hatırlayınız. Eğer çekirdek içerisindeki yer alan kodlarda herhangi bir kritik hata oluşması nedeniyle tüm çekirdek çalışamaz hale gelirse, sistemin panic parametresi ile açılmış olması halinde otomatik yeniden başlatma (reset) işlemi çekirdek tarafından yapılmaktadır.

Ancak bu yöntem sadece çekirdek seviyesindeki hatalarda işe yaramaktadır. Watchdog ise kullanıcı kipi hatalarını da yakalamaya ve bir şeyler ters gittiğinde en azından sisteminizi yeniden başlatabilmenize imkan tanımaktadır.

Çekirdek Desteği

Sistemdeki watchdog donanımının kullanımı için çekirdek seviyesinde sürücü desteği sağlanmış olmalıdır.

Linux çekirdeğinde watchdog donanım sürücüleri için genel bir Watchdog Driver API mevcut olup, tüm donanımlar tarafından aynı arayüz, yetenekleri doğrultusunda sağlanır. Detaylar için https://www.kernel.org/doc/Documentation/watchdog/watchdog-api.txt belgesini inceleyebilirsiniz.

Temel Kullanım Modu

Tüm watchdog sürücülerinin en az bu modu desteklemesi beklenir, dolayısıyla watchdog donanımızın desteklenmesi halinde her durumda bu çalışma yöntemini kullanabilirsiniz.

Çalışma mantığı şu şekildedir:

  • Uygulama katmanında /dev/watchdog aygıt dosyası yazma modunda açılır

  • Öntanımlı olarak 60 saniyelik bir zamanlayıcı başlar

  • 60 saniye dolmadan, bu dosyaya herhangi bir veri yazılır (tek karakter de olabilir) ve zamanlayıcının yeniden başlatılması sağlanır

  • Uygulama, kendi içinde bir döngüde kalıp zamanında watchdog dosyasına yeni bir veri yazamaz ise, süre dolumunda sistem yeniden başlatılır

  • Açık durumdaki /dev/watchdog dosyası kapatılır ise, watchdog sistemi devre dışı bırakılır

Görüleceği üzere Unix sistemlerde hemen her şeyin dosya arayüzü ile kullanıcı katmanına sunumu yaklaşımı burada da benimsenmiştir. Uygulamanız içerisinde yukarıdaki iş akışını dosya işlemleriyle kolaylıkla gerçekleyebilirsiniz.

Yalnız burada dikkat edilmesi gereken husus, /dev/watchdog dosyasının yazma modunda açılması ile başlayan zamanlayıcının dosyanın kapatılması halinde devre dışı kalıyor oluşudur. İlk başta önemli bir problem olarak görünmeyebilir, ancak Linux çekirdeği herhangi bir yöntemle sonlanan kullanıcı kipi uygulamaları için, açık halde bulunan tüm dosyaları da kapatır. Bu nedenle watchdog mekanizmasını işletmek için uygulamanızda /dev/watchdog açık halde iken uygulamanız kontrolsüz biçimde sonlanacak olursa, dosya kapatıldığı için watchdog da devre dışı kalacak ve beklediğiniz zamanlayıcı süresi dolumundaki yeniden başlatma işlemi gerçekleşmeyecektir.

Peki o halde watchdog ne işe yarayacak diye sorabilirsiniz. Endişeye mahal yok.

Bu dizayn ile temelde 3 çözüm yönteminiz bulunuyor:

  1. Ana uygulama(ları)nız içerisinde watchdog yönetmek yerine, watchdog'u yöneten ayrı bir uygulama yazmak (veya hazır bir watchdog daemon kullanmak)

  2. Magic Close özelliği destekleniyorsa kullanmak

  3. Çekirdek derleme sürecinde CONFIG_WATCHDOG_NOWAYOUT opsiyonu seçerek, sürücünüzün de desteklemesi halinde watchdog dosyasının kapanmasıyla zamanlayıcının durdurulmasını engellemek

Magic Close Özelliği

Bazı sürücüler Magic Close adı verilen bir özelliği desteklemektedir. Bu destek sayesinde, watchdog dosyası kapatılmadan önce V karakteri dosyaya yazılmaz ise, dosya kapatılsa dahi zamanlayıcı çalışmaya devam etmekte ve zamanı dolduğunda sistemi yeniden başlatmaktadır.

Eğer özellikle watchdog zamanlayıcısını durdurmak istiyorsanız, dosyayı kapamadan önce V karakterini yazabilir ve sonra kapama işlemini gerçekleştirebilirsiniz.

Magic Close desteği daha rahat bir kontrol sağlıyor olmasına karşın sisteminizde desteklenmiyor olması ihtimali kuvvetle muhtemeldir. Bu özelliğin desteklenip desteklenmediğini ioctl arayüzü üzerinden WDIOC_GETSUPPORT opsiyonuyla sorgulayabilirsiniz. Aşağıdaki örnek uygulama ile watchdog sürücünüzün Magic Close, Set Timeout ve Keep Alive Ping özelliklerini destekleyip desteklemediğini öğrenebilirsiniz:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>

#define WATCHDOG_DEVICE "/dev/watchdog"

int main(void)
{
    struct watchdog_info info;
    int fd;

    if ( (fd = open(WATCHDOG_DEVICE, O_RDWR)) < 0) {
        perror("open failure");
        exit(EXIT_FAILURE);
    }

    if (ioctl(fd, WDIOC_GETSUPPORT, &info) < 0) {
        perror("ioctl");
        exit(EXIT_FAILURE);
    }

    printf("Magic Close Feature  : %s\n", (info.options & WDIOF_MAGICCLOSE) ? "Yes" : "No");
    printf("Set Timeout Feature  : %s\n", (info.options & WDIOF_SETTIMEOUT) ? "Yes" : "No");
    printf("KeepAlivePing Feature: %s\n", (info.options & WDIOF_KEEPALIVEPING) ? "Yes" : "No");

    close(fd);
}

ioctl Arayüzü

Tüm watchdog sürücüleri, destekledikleri özellikler için ioctl arayüzü de sağlamaktadırlar.

Watchdog zamanlayıcıyı beslemek ve yeni bir tur daha süre kazanmak için WDIOC_KEEPALIVE ile aşağıdaki gibi bir ioctl çağrısı yapabilirsiniz. 3. parametrenin ne olduğunun bir önemi yoktur:

ioctl(fd, WDIOC_KEEPALIVE, 0);

Sürücü tarafından desteklenmesi halinde 60 saniyelik öntanımlı watchdog zamanlayıcı değerini değiştirmek isterseniz, WDIOC_SETTIMEOUT ile aşağıdaki gibi bir ioctl çağrısı yapabilirsiniz:

int timeout = 20; /* saniye */
ioctl(fd, WDIOC_SETTIMEOUT, &timeout);

Benzer şekilde, zamanlayıcıda kalan zamanı WDIOC_GETTIMEOUT ile aşağıdaki gibi sorgulayabilirsiniz:

int remaining;
ioctl(fd, WDIOC_GETTIMEOUT, &remaining);

Sistemin son defa yeniden başlatılması işleminin watchdog yüzünden olup olmadığını WDIOC_GETBOOTSTATUS ile sorgulayabilirsiniz:

int bootfromwatchdog;
ioctl(fd, WDIOC_GETBOOTSTATUS, &bootfromwatchdog);

Daha detaylı özellikler için çekirdek içerisindeki dokümantasyonu inceleyebilirsiniz.

results matching ""

    No results matching ""