Güç Yönetimi & Thermal
TEKNİK REHBER GÜÇ YÖNETİMİ WATCHDOG 2026

Watchdog Timer —
/dev/watchdog.

/dev/watchdog API'si, systemd WatchdogSec entegrasyonu, pretimeout handler ve BCM2835/i.MX/STM32 IWDG platform detayları — sistemi kilitmeden kurtar.

00 Watchdog nedir — hardware vs software WDT

Watchdog timer, yazılımın kendisini periyodik olarak "ben hâlâ çalışıyorum" diye onaylamasını gerektirir. Onay gelmezse donanım sistemi sıfırlar.

Neden gerekli?

Gömülü sistemlerde yazılım birçok nedenden dolayı kilitlenebilir: sonsuz döngü, deadlock, bellek bozulması, kernel panik. İnsan müdahalesi mümkün olmayan uzak veya güvenlik-kritik sistemlerde watchdog, son savunma hattıdır.

Hardware WDT
CPU dışı bağımsız bir sayaç. CPU tamamen kilitlense bile çalışır. En güvenilir yöntem. Her SoC'da genellikle mevcuttur (WDOG, IWDG, vb.).
Software WDT (softdog)
Kernel timer tabanlı watchdog. Donanım WDT yoksa kullanılır. Kernel donduğunda çalışmaz — güvenilirlik sınırlı.
External WDT
Ayrı bir mikrodenetleyici (STM8, PIC) GPIO sinyal bekler. En yüksek güvenilirlik — ana işlemci tamamen ölse de reset atar.

Temel çalışma prensibi

WDT akış diyagramı
Uygulama başlar
    │
    ├─ /dev/watchdog açılır  → WDT başlar (örn. 30sn)
    │
    ├─ Döngü: iş yap → watchdog besle (her ~10sn)
    │              │
    │              └─ WDT sayacı sıfırlanır
    │
    ├─ Kilitlenme!
    │              │
    │              └─ watchdog beslenmez
    │                         │
    │              timeout (30sn) dolunca
    │                         │
    └──────────────────── HARDWARE RESET
KRİTİK

/dev/watchdog'u açtıktan sonra beslemezseniz sistem resetlenir. Test ortamında her zaman "magic close" mekanizmasını doğru kullanın: dosyayı kapatmadan önce 'V' karakteri yazın.

01 /dev/watchdog API — open, write, ioctl

Linux watchdog UAPI basittir: aç, besle, kapat. Tüm kontrol /dev/watchdog üzerinden ioctl ile yapılır.

Temel C API

c — watchdog temel kullanım
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>

int main(void) {
    int fd, timeout = 30;

    /* WDT aç — bu noktadan itibaren beslenmezse reset gelir */
    fd = open("/dev/watchdog", O_RDWR);
    if (fd < 0) { perror("open /dev/watchdog"); return 1; }

    /* Zaman aşımını ayarla (saniye) */
    if (ioctl(fd, WDIOC_SETTIMEOUT, &timeout) < 0) {
        perror("WDIOC_SETTIMEOUT");
    }

    /* Gerçek timeout'u oku (donanım en yakın desteklenen değere yuvarlar) */
    ioctl(fd, WDIOC_GETTIMEOUT, &timeout);
    printf("WDT timeout: %d saniye\n", timeout);

    /* Keepalive döngüsü */
    for (int i = 0; i < 10; i++) {
        sleep(10);

        /* Yöntem 1: write() ile besle */
        write(fd, "1", 1);

        /* Yöntem 2: ioctl ile besle */
        /* ioctl(fd, WDIOC_KEEPALIVE, 0); */

        printf("WDT beslendi (%d/10)\n", i + 1);
    }

    /* Magic close: 'V' yazarak güvenli kapat */
    write(fd, "V", 1);
    close(fd);
    printf("WDT durduruldu (magic close)\n");

    return 0;
}

IOCTL komutları

WDIOC_GETSUPPORT
struct watchdog_info ile WDT özelliklerini oku: firma adı, sürüm, desteklenen WDIOF_ flagler.
WDIOC_GETSTATUS / WDIOC_GETBOOTSTATUS
WDT durum flagleri. WDIOF_CARDRESET: son önyükleme WDT resetinden mi oldu?
WDIOC_SETTIMEOUT / WDIOC_GETTIMEOUT
Timeout süresini ayarla/oku (saniye). Donanım en yakın değere yuvarlar.
WDIOC_KEEPALIVE
WDT sayacını sıfırla (besle). write() ile eşdeğer.
WDIOC_SETOPTIONS
WDIOS_DISABLECARD: WDT durdur. WDIOS_ENABLECARD: WDT başlat.
WDIOC_SETPRETIMEOUT / WDIOC_GETPRETIMEOUT
Pre-timeout süresini ayarla: gerçek timeout'tan bu kadar saniye önce uyarı verilir.
c — WDT destek sorgulama
#include <linux/watchdog.h>

struct watchdog_info info;
ioctl(fd, WDIOC_GETSUPPORT, &info);

printf("Identity: %s\n",    info.identity);
printf("Firmware: %u\n",    info.firmware_version);
printf("Options:  0x%08x\n", info.options);

/* WDIOF flag'leri kontrol et */
if (info.options & WDIOF_SETTIMEOUT)
    printf("  - Timeout ayarlanabilir\n");
if (info.options & WDIOF_KEEPALIVEPING)
    printf("  - Keepalive destekleniyor\n");
if (info.options & WDIOF_MAGICCLOSE)
    printf("  - Magic close destekleniyor\n");
if (info.options & WDIOF_PRETIMEOUT)
    printf("  - Pre-timeout destekleniyor\n");

/* Son reset WDT'den mi? */
int boot_status;
ioctl(fd, WDIOC_GETBOOTSTATUS, &boot_status);
if (boot_status & WDIOF_CARDRESET)
    printf("Son reset: WDT reset!\n");

02 Kernel watchdog driver — struct watchdog_device

Linux watchdog core, platform-specific WDT donanımını soyutlayan birleşik bir altyapı sağlar. Yeni bir WDT driver yazmak için watchdog_device struct'ını ve ops'larını doldurmak yeterlidir.

c — minimal watchdog driver
#include <linux/watchdog.h>
#include <linux/platform_device.h>

struct mywdt_priv {
    void __iomem       *base;
    struct watchdog_device wdd;
};

static int mywdt_start(struct watchdog_device *wdd)
{
    struct mywdt_priv *priv = watchdog_get_drvdata(wdd);
    /* Donanımı başlat */
    writel(WDT_ENABLE | WDT_RESET_ON_TIMEOUT,
           priv->base + WDT_CTRL_REG);
    return 0;
}

static int mywdt_stop(struct watchdog_device *wdd)
{
    struct mywdt_priv *priv = watchdog_get_drvdata(wdd);
    writel(0, priv->base + WDT_CTRL_REG);
    return 0;
}

static int mywdt_ping(struct watchdog_device *wdd)
{
    struct mywdt_priv *priv = watchdog_get_drvdata(wdd);
    /* Sayacı sıfırla */
    writel(WDT_KICK_VALUE, priv->base + WDT_KICK_REG);
    return 0;
}

static int mywdt_set_timeout(struct watchdog_device *wdd,
                              unsigned int timeout)
{
    struct mywdt_priv *priv = watchdog_get_drvdata(wdd);
    u32 count = timeout * WDT_CLK_FREQ;
    writel(count, priv->base + WDT_LOAD_REG);
    wdd->timeout = timeout;
    return 0;
}

static const struct watchdog_ops mywdt_ops = {
    .owner       = THIS_MODULE,
    .start       = mywdt_start,
    .stop        = mywdt_stop,
    .ping        = mywdt_ping,
    .set_timeout = mywdt_set_timeout,
};

static const struct watchdog_info mywdt_info = {
    .options  = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
    .identity = "MyPlatform WDT",
};

static int mywdt_probe(struct platform_device *pdev)
{
    struct mywdt_priv *priv;
    struct resource *res;

    priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
    if (!priv) return -ENOMEM;

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    priv->base = devm_ioremap_resource(&pdev->dev, res);
    if (IS_ERR(priv->base)) return PTR_ERR(priv->base);

    priv->wdd.info       = &mywdt_info;
    priv->wdd.ops        = &mywdt_ops;
    priv->wdd.timeout    = 30;   /* default 30s */
    priv->wdd.min_timeout = 1;
    priv->wdd.max_timeout = 128;
    priv->wdd.parent     = &pdev->dev;

    watchdog_set_drvdata(&priv->wdd, priv);
    watchdog_set_nowayout(&priv->wdd, nowayout);

    return devm_watchdog_register_device(&pdev->dev, &priv->wdd);
}
nowayout parametresi

nowayout=1 modülü yüklendiğinde magic close çalışmaz — WDT bir kez açıldıktan sonra kapatılamaz. Üretim sistemleri için önerilir; test sırasında false resetleri önlemek için 0 kullanın.

03 systemd watchdog entegrasyonu

systemd, watchdog'u kendi servis izleme sistemiyle entegre eder. Servis belirli aralıklarla "ben sağlıklıyım" bildirimi göndermezse systemd servisi yeniden başlatır; daha uzun sürede yanıt gelmezse sistem resetlenir.

systemd watchdog yapılandırması

/etc/systemd/system.conf — sistem geneli WDT
[Manager]
RuntimeWatchdogSec=30s   # sistemin WDT timeout'u
RebootWatchdogSec=10min  # reboot sırasında WDT timeout
KExecWatchdogSec=10min   # kexec sırasında WDT timeout
servis dosyası — WatchdogSec
[Unit]
Description=Kritik Sensör Daemon

[Service]
Type=notify
ExecStart=/usr/local/bin/sensor-daemon

# Servis 20 saniyede bir sd_notify(WATCHDOG=1) çağırmalı
WatchdogSec=20s

# WDT timeout'u aşılırsa ne yap?
Restart=on-watchdog        # servisi yeniden başlat
RestartSec=5s

# veya sistem reset için:
# WatchdogSignal=SIGABRT   # önce ABRT, sonra reset

[Install]
WantedBy=multi-user.target

sd_notify API ile servis içi watchdog

c — sd_notify ile watchdog
#include <systemd/sd-daemon.h>
#include <stdint.h>
#include <time.h>

int main(void) {
    uint64_t watchdog_usec = 0;
    struct timespec ts;

    /* systemd watchdog interval'ını öğren */
    sd_watchdog_enabled(0, &watchdog_usec);
    uint64_t interval_usec = watchdog_usec / 2;  /* interval/2 sıklıkla besle */

    /* Hazır olduğunu bildir */
    sd_notify(0, "READY=1\nSTATUS=Sensör daemon başladı");

    while (1) {
        /* ... iş yap ... */
        do_sensor_reading();

        /* WDT besle */
        sd_notify(0, "WATCHDOG=1");

        /* İsteğe bağlı: durum güncelle */
        sd_notifyf(0, "WATCHDOG=1\nSTATUS=Ölçüm #%d tamamlandı",
                   reading_count++);

        /* Hesaplanan interval kadar bekle */
        usleep(interval_usec);
    }
    return 0;
}
/* Derleme: gcc ... -lsystemd */
python3 — sd_notify Python
#!/usr/bin/env python3
import os, time, socket

def sd_notify(msg):
    """systemd sd_notify() Python uygulaması"""
    addr = os.environ.get("NOTIFY_SOCKET")
    if not addr: return
    if addr.startswith('@'):
        addr = '\0' + addr[1:]
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    sock.sendto(msg.encode(), addr)
    sock.close()

# Başlangıç
sd_notify("READY=1\nSTATUS=başlatıldı")

count = 0
while True:
    time.sleep(5)
    count += 1
    # Watchdog besle
    sd_notify(f"WATCHDOG=1\nSTATUS=döngü {count}")
    print(f"WDT beslendi (döngü {count})")
bash — systemd WDT durumunu kontrol et
# Sistemin WDT kullandığını doğrula
systemctl show | grep -i watchdog
# RuntimeWatchdogUSec=30s
# RuntimeWatchdogPreUSec=0

# servis watchdog durumu
systemctl status sensor-daemon.service | grep -i watchdog

04 Pretimeout — önceden uyarı ve panic

Pretimeout, gerçek WDT resetinden önce belirli bir süre içinde kernel'a veya kullanıcı alanına uyarı verir. Bu sürede teşhis bilgisi toplanabilir veya kontrollü kapatma yapılabilir.

c — pretimeout ayarı
#include <linux/watchdog.h>

int fd = open("/dev/watchdog", O_RDWR);

int timeout = 30;
int pretimeout = 5;   /* resetden 5 saniye önce uyar */

ioctl(fd, WDIOC_SETTIMEOUT,    &timeout);
ioctl(fd, WDIOC_SETPRETIMEOUT, &pretimeout);

int actual_pre;
ioctl(fd, WDIOC_GETPRETIMEOUT, &actual_pre);
printf("Pretimeout: %d saniye resetden önce\n", actual_pre);

watchdog_pretimeout_governor

noop
Hiçbir şey yapma. Sadece pretimeout event üretilir (logging için kullanışlı).
panic
Kernel panic tetikler. kdump ile panic dump alınabilir — teşhis için en yararlı seçenek.
bash — pretimeout governor
# mevcut pretimeout governor'ları
ls /sys/bus/platform/drivers/ | grep pretimeout
cat /sys/kernel/debug/watchdog0/pretimeout_governor
# noop

# panic governor'a geç (kernel panic + kdump)
echo panic > /sys/kernel/debug/watchdog0/pretimeout_governor

# systemd ile pretimeout
# /etc/systemd/system.conf içine:
# RuntimeWatchdogPreUSec=5s
KDump İLE BİRLİKTE

Pretimeout + panic + kdump kombinasyonu, production sistemlerde "neden kilitlendi?" sorusunu yanıtlamak için en güçlü araçtır. Pretimeout'ta kernel panic tetiklenince kdump crash dump kaydeder, sonra asıl WDT reset atar ve sistem yeniden başlar.

05 watchdog-d daemon — /etc/watchdog.conf

watchdog-d (veya watchdog paketi), /dev/watchdog'u yöneten, çeşitli sistem sağlık testlerini yapan hazır bir daemon'dur.

bash — kurulum
# Debian/Ubuntu
apt install watchdog

# servis başlat
systemctl enable --now watchdog

/etc/watchdog.conf açıklamalı

/etc/watchdog.conf
# WDT cihaz dosyası
watchdog-device = /dev/watchdog

# WDT timeout (saniye)
watchdog-timeout = 30

# Kaç saniyede bir besle
interval = 10

# Sıcaklık eşiği (°C) — /sys/class/thermal/ veya hwmon
#temperature-device = /dev/cpu_temp0
#max-temperature = 90

# CPU yük ortalaması testi
max-load-1  = 24    # 1dk load average > 24 ise hata
max-load-5  = 18    # 5dk load average
max-load-15 = 12    # 15dk load average

# Bellek testi
min-memory = 1      # MB cinsinden minimum free bellek
#allocatable-memory = 1

# Dosya değişiklik testi (dosya güncellenmezse hata)
#file = /var/run/heartbeat.pid
#change = 60        # 60 saniyede değişmeli

# Dosya erişilebilirlik testi
#file = /var/run/myapp.pid

# PID dosyası — process çalışıyor mu?
#pidfile = /var/run/sshd.pid

# Özel test scripti
#test-binary = /usr/local/bin/wdt-health-check.sh
#test-timeout = 5   # script 5 saniyede bitirmeli

# Hata durumunda ne yap
repair-binary = /usr/local/bin/wdt-repair.sh

# Log
log-dir = /var/log/watchdog
verbose = 0
bash — custom health check scripti
#!/bin/bash
# /usr/local/bin/wdt-health-check.sh
# watchdog test-binary olarak çağrılır
# Başarı: exit 0, Hata: exit 1

# I2C sensör erişilebilir mi?
if ! i2cdetect -y 1 2>/dev/null | grep -q "^20:"; then
    logger -p daemon.error "WDT: I2C sensor kayboldu!"
    exit 1
fi

# Kritik servis çalışıyor mu?
if ! systemctl is-active --quiet mqtt-bridge.service; then
    logger -p daemon.error "WDT: mqtt-bridge durdu!"
    exit 1
fi

# Disk yazılabilir mi?
if ! touch /tmp/wdt_test 2>/dev/null; then
    logger -p daemon.error "WDT: disk yazılamıyor!"
    exit 1
fi
rm -f /tmp/wdt_test

exit 0

06 Platform WDT: BCM2835, i.MX WDOG, STM32 IWDG

Her SoC'un kendi WDT donanımı ve driver'ı vardır. Üç yaygın platform için notlar.

Raspberry Pi — BCM2835/BCM2711 WDT

dts / bash — BCM2835 WDT
# BCM2835 WDT device tree node (Pi 4)
# bcm2835-wdt otomatik yüklenir — kernel config: CONFIG_BCM2835_WDT=y

# Driver yüklü mü?
dmesg | grep bcm2835_wdt
# bcm2835-wdt: Broadcom BCM2835 watchdog timer

cat /sys/devices/platform/soc/1c000000.watchdog/identity 2>/dev/null ||
cat /sys/class/watchdog/watchdog0/identity
# Broadcom BCM2835 Watchdog timer

# Maksimum timeout: ~15 saniye (BCM2835 sınırlaması)
cat /sys/class/watchdog/watchdog0/max_timeout
# 15

# BCM2711 (Pi 4): daha uzun timeout destekler
# PM kütüphanesi üzerinden de kontrol edilebilir

i.MX WDOG (NXP i.MX6/7/8)

dts — i.MX6 WDOG
wdog1: watchdog@20bc000 {
    compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
    reg = <0x020bc000 0x4000>;
    interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
    clocks = <&clks IMX6QDL_CLK_IPG>;
};
bash — i.MX WDOG kullanım
# i.MX WDOG kernel config: CONFIG_IMX2_WDT=y
dmesg | grep imx2_wdt
# imx2-wdt 20bc000.watchdog: Initial timeout: 60s

# i.MX WDOG maksimum timeout: ~128 saniye
cat /sys/class/watchdog/watchdog0/max_timeout
# 128

# i.MX WDOG reset kaynağını kontrol et
# SRC (System Reset Controller) registerı
devmem2 0x020D8008 w  # SRC_SRSR: reset status register
# bit[4]: WDOG reset bit

STM32 IWDG ve WWDG

dts — STM32 IWDG
/* STM32MP157 IWDG (Independent Watchdog) */
iwdg2: watchdog@5a002000 {
    compatible = "st,stm32mp1-iwdg";
    reg = <0x5a002000 0x400>;
    clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
    clock-names = "pclk", "lsi";
    timeout-sec = <32>;
    status = "okay";
};

/* WWDG (Window Watchdog) — pencereli WDT */
wwdg: watchdog@40002c00 {
    compatible = "st,stm32-wwdg";
    reg = <0x40002c00 0x400>;
    clocks = <&rcc WWDG1K>;
    /* min ve max arasında beslenmeli! */
};
IWDG (Independent WDT)
LSI osilatörüne bağlı, CPU clock'undan bağımsız. Çok derin uyku dahil her durumda çalışır. STM32 gömülü için tercih edilir.
WWDG (Window WDT)
Pencereli: belirli bir zaman penceresinin dışında besleme yapmak reset atar. "Çok erken besleme" de hata sayılır — yazılım donduğunda değil, anormal davrandığında da müdahale eder.

07 Yocto/Buildroot — WDT enablement

Gömülü Linux dağıtımlarında WDT genellikle varsayılan olarak devre dışıdır. Yocto ve Buildroot'ta etkinleştirme adımları.

Yocto

yocto — layer.conf ve recipe
# local.conf veya distro.conf
DISTRO_FEATURES:append = " watchdog"

# kernel konfigürasyonu (meta-layer/recipes-kernel/linux/linux-yocto.bbappend)
KERNEL_EXTRA_FEATURES:append = " watchdog.scc"

# watchdog paketi ekle
IMAGE_INSTALL:append = " watchdog"

# systemd entegrasyonu için (meta-systemd)
IMAGE_INSTALL:append = " systemd-conf"
yocto — watchdog recipe bbappend
# meta-myboard/recipes-support/watchdog/watchdog_%.bbappend
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"

SRC_URI:append = " file://watchdog.conf"

do_install:append() {
    install -d ${D}${sysconfdir}
    install -m 0644 ${WORKDIR}/watchdog.conf ${D}${sysconfdir}/watchdog.conf
}

Buildroot

buildroot — menuconfig seçenekleri
# make menuconfig içinde:
# Target packages → System tools → watchdog utilities
BR2_PACKAGE_WATCHDOG=y

# Kernel config fragment (board/myboard/linux.config)
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
CONFIG_BCM2835_WDT=y   # ya da platform-specific
CONFIG_SOFT_WATCHDOG=y  # yedek olarak softdog

Systemd servis — önyükleme sırasında WDT başlatma

/etc/systemd/system/watchdog-start.service
[Unit]
Description=Start Hardware Watchdog
DefaultDependencies=no
Before=sysinit.target
After=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=yes
# WDT modülünü yükle (gerekirse)
ExecStartPre=-/sbin/modprobe bcm2835_wdt
# watchdog daemon başlat
ExecStart=/sbin/watchdogd -F -c /etc/watchdog.conf

[Install]
WantedBy=sysinit.target

08 Pratik: Python watchdog daemon ve kill testi

Python ile tam watchdog keepalive daemon, ardından kill testi ile hardware reset'i gözlemleme.

Python watchdog daemon

python3 — watchdog_daemon.py
#!/usr/bin/env python3
"""
Watchdog keepalive daemon.
- /dev/watchdog'u açar, timeout ayarlar
- Her FEED_INTERVAL saniyede bir besler
- Sağlık kontrolü başarısız olursa beslemeyi durdurur → reset
"""
import os, fcntl, struct, time, signal, logging, subprocess

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(message)s',
    datefmt='%H:%M:%S'
)
log = logging.getLogger("wdt")

# /usr/include/linux/watchdog.h değerleri
WDIOC_SETTIMEOUT  = 0xC0045706
WDIOC_GETTIMEOUT  = 0x80045707
WDIOC_KEEPALIVE   = 0x80002705
WDIOC_GETBOOTSTATUS = 0x80045702
WDIOF_CARDRESET   = 0x0020

WDT_DEVICE    = "/dev/watchdog"
WDT_TIMEOUT   = 30      # saniye
FEED_INTERVAL = 10      # saniye — timeout/3
MAGIC_CLOSE   = b'V'

class WatchdogDaemon:
    def __init__(self):
        self.fd = None
        self.running = True
        signal.signal(signal.SIGTERM, self._shutdown)
        signal.signal(signal.SIGINT,  self._shutdown)

    def _shutdown(self, *args):
        log.info("Kapatma sinyali alındı")
        self.running = False

    def open(self):
        self.fd = os.open(WDT_DEVICE, os.O_RDWR)

        # Boot status kontrol
        buf = struct.pack('I', 0)
        res = fcntl.ioctl(self.fd, WDIOC_GETBOOTSTATUS, buf)
        boot_status = struct.unpack('I', res)[0]
        if boot_status & WDIOF_CARDRESET:
            log.warning("Son reboot WDT resetinden! Sistem kilitlenmesi oldu.")

        # Timeout ayarla
        buf = struct.pack('I', WDT_TIMEOUT)
        res = fcntl.ioctl(self.fd, WDIOC_SETTIMEOUT, buf)
        actual = struct.unpack('I', res)[0]
        log.info(f"WDT açıldı, timeout={actual}s, besle={FEED_INTERVAL}s")

    def feed(self):
        """WDT besle"""
        os.write(self.fd, b'1')

    def close_safe(self):
        """Magic close — WDT'yi güvenli durdur"""
        if self.fd is not None:
            os.write(self.fd, MAGIC_CLOSE)
            os.close(self.fd)
            self.fd = None
            log.info("WDT magic close ile durduruldu")

    def health_check(self):
        """Sistem sağlık kontrolü — False döndürürse besleme durur"""
        # Kritik servis çalışıyor mu?
        ret = subprocess.run(
            ["systemctl", "is-active", "--quiet", "sshd"],
            capture_output=True
        )
        if ret.returncode != 0:
            log.error("sshd çalışmıyor!")
            return False

        # Disk alanı kontrolü (minimum 10MB)
        stat = os.statvfs("/")
        free_mb = (stat.f_bavail * stat.f_frsize) / (1024 * 1024)
        if free_mb < 10:
            log.error(f"Disk doldu: {free_mb:.1f}MB kaldı!")
            return False

        return True

    def run(self):
        self.open()
        try:
            while self.running:
                if self.health_check():
                    self.feed()
                    log.debug("WDT beslendi, sistem sağlıklı")
                else:
                    log.critical("SAĞLIK KONTROLÜ BAŞARISIZ — WDT beslenmeyecek!")
                    # Beslemeyi durdur, reset bekle
                    while True:
                        time.sleep(1)

                time.sleep(FEED_INTERVAL)
        finally:
            self.close_safe()

if __name__ == "__main__":
    daemon = WatchdogDaemon()
    daemon.run()

Kill testi — hardware reset gözlemleme

bash — WDT kill testi
# 1. Daemon'ı başlat
python3 watchdog_daemon.py &
WDT_PID=$!
echo "WDT daemon PID: $WDT_PID"

# 2. Normal çalıştığını doğrula (30 saniye izle)
sleep 30
echo "Sistem hâlâ çalışıyor — WDT düzgün besleniyor"

# 3. Daemon'ı kill et (SIGKILL — magic close yapamaz)
echo "WDT daemon'ını öldürüyoruz..."
kill -9 $WDT_PID

# 4. WDT_TIMEOUT saniye bekle → sistem resetlenecek
# Bu noktadan sonra terminal oturumu kapanır!
echo "WDT beslenmeyecek, $WDT_TIMEOUT saniye içinde reset bekleniyor..."

# 5. Reboot sonrası — WDT resetinden mi önyüklendi?
dmesg | grep -i "watchdog\|wdt\|reset"
# bcm2835-wdt: Watchdog reset triggered

# 6. Boot status kontrolü
python3 -c "
import os, fcntl, struct
WDIOC_GETBOOTSTATUS = 0x80045702
WDIOF_CARDRESET     = 0x0020
fd = os.open('/dev/watchdog', os.O_RDWR)
buf = struct.pack('I', 0)
res = fcntl.ioctl(fd, WDIOC_GETBOOTSTATUS, buf)
status = struct.unpack('I', res)[0]
print('WDT reset:', bool(status & WDIOF_CARDRESET))
os.write(fd, b'V')
os.close(fd)
"
BEKLENEN SONUÇ

kill -9 ile daemon öldürüldükten WDT_TIMEOUT (30) saniye sonra sistem resetlenir. Reboot sonrası WDIOC_GETBOOTSTATUS WDIOF_CARDRESET bitini set gösterir. dmesg'de "Watchdog reset triggered" veya benzeri mesaj görülür. Bu, hardware WDT'nin yazılımdan bağımsız olarak düzgün çalıştığını doğrular.