聊一聊Linux內(nèi)核中Watchdog
本文轉(zhuǎn)載自微信公眾號(hào)「相遇Linux」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系相遇Linux公眾號(hào)。
在Linux內(nèi)核中有三個(gè)watchdog(看門狗),它們都需要被悉心的喂養(yǎng)照料,分別是:
1. /dev/watchdog
2.softlockup檢測(cè)機(jī)制
3.hardlockup檢測(cè)機(jī)制
首先看 1./dev/watchdog,此看門狗該怎樣喂養(yǎng)呢,linux內(nèi)核中有一段樣例代碼:
- samples/watchdog/watchdog-simple.c
- // SPDX-License-Identifier: GPL-2.0
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- int main(void)
- {
- int fd = open("/dev/watchdog", O_WRONLY);
- int ret = 0;
- if (fd == -1) {
- perror("watchdog");
- exit(EXIT_FAILURE);
- }
- while (1) {
- ret = write(fd, "\0", 1);
- if (ret != 1) {
- ret = -1;
- break;
- }
- sleep(10);
- }
- close(fd);
- return ret;
- }
此例子中,每隔10秒鐘就會(huì)向“/dev/watchdog" 文件寫入0, 這就是喂狗過程,看到這個(gè)樣例,好像不太能感受到這個(gè)看門狗大的用處,但是放在實(shí)際工程中,用處太大了,舉個(gè)例子:
某國(guó)中央銀行在一臺(tái)有 內(nèi)存4T, 320個(gè)cpu核 的Linux服務(wù)器上跑一個(gè)數(shù)據(jù)庫(kù)程序,數(shù)據(jù)庫(kù)上存有他本國(guó)所有人民的銀行賬號(hào)信息,當(dāng)此數(shù)據(jù)庫(kù)程序在運(yùn)行過程中,發(fā)生了IO讀寫錯(cuò)誤,或者程序bug, 一下卡住了,那么他本國(guó)人民就都不能存錢取錢轉(zhuǎn)賬了,整個(gè)國(guó)民經(jīng)濟(jì)瞬間癱瘓。
此時(shí)想想看,Linux系統(tǒng)有沒有什么機(jī)制來解決這種問題了,這時(shí)候“/dev/watchdog" 來了,
這個(gè)時(shí)候只需要在數(shù)據(jù)庫(kù)程序中加上類似上面的樣例程序,每隔10s中就去喂狗一次,
只要數(shù)據(jù)庫(kù)程序卡住,卡住之后就不能喂狗了,等到比如默認(rèn)60s以后,這只狗就罷工了,立馬會(huì)默認(rèn)觸發(fā)服務(wù)器重啟。
服務(wù)器重啟會(huì)重新加載數(shù)據(jù)庫(kù)程序, 或者服務(wù)器在重啟過程中,由于服務(wù)器與它所在的服務(wù)器集群失聯(lián),從而觸發(fā)集群中的分腦檢測(cè),把數(shù)據(jù)庫(kù)程序挪到集群中其它設(shè)備上跑, 此時(shí)就減少了很多損失. 所以這只狗/dev/watchdog 用處太大了。
再來看下它的實(shí)現(xiàn)原理:
- #ps -ef | grep watchdog
- root 104 2 0 2020 ? 00:00:00 [watchdogd]
- #ls -l /dev/watchdog*
- crw------- 1 root root 10, 130 Dec 30 20:04 /dev/watchdog
- crw------- 1 root root 247, 0 Dec 30 20:04 /dev/watchdog0
看到系統(tǒng)中有個(gè)內(nèi)核線程watchdogd, 和兩個(gè)字符文件:/dev/watchdog和/dev/watchdog0
其中watchdogd實(shí)時(shí)調(diào)度類線程負(fù)責(zé)具體執(zhí)行喂狗,/dev/watchdog是內(nèi)核提供給用戶層的通用操作接口文件,用來開啟這只狗,喂狗,查詢狀態(tài)等。/dev/watchdog0 是具體的狗子實(shí)現(xiàn),可以基于具體的物理設(shè)備實(shí)現(xiàn),或者是softdog內(nèi)核模塊以軟件的方式(具體使用方法:modprobe softdog)模擬硬件實(shí)現(xiàn)。
來看下softdog內(nèi)核模塊怎樣模擬硬件實(shí)現(xiàn)這個(gè)功能:
- static int __init softdog_init(void)
- hrtimer_init(&softdog_ticktock, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- softdog_ticktock.function = softdog_fire;
- static enum hrtimer_restart softdog_fire(struct hrtimer *timer)
- emergency_restart();
- static int softdog_ping(struct watchdog_device *w)
- hrtimer_start(&softdog_ticktock, ktime_set(w->timeout, 0), (60s)
- HRTIMER_MODE_REL);
從代碼實(shí)現(xiàn)來看,很好理解,在開啟看門狗(open "/dev/watchdog")之后,默認(rèn)60s以后就會(huì)觸發(fā)系統(tǒng)重啟,在60s倒計(jì)時(shí)過程中,只有喂狗(softdog_ping)一次,它就又會(huì)恢復(fù)到60s以后才會(huì)觸發(fā)系統(tǒng)重啟,所以只要一直喂狗,emergency_restart()就不會(huì)執(zhí)行,系統(tǒng)就不會(huì)重啟。
再來看下 2.softlockup檢測(cè)機(jī)制 和 3.hardlockup檢測(cè)機(jī)制。
softlockup檢測(cè)機(jī)制的喂狗方式是,每cpu上的hrtimer會(huì)喚醒一個(gè)migration/N內(nèi)核線程,migration/N每次被喚醒之后都會(huì)對(duì)某個(gè)時(shí)間戳進(jìn)行重置。
hardlockup檢測(cè)機(jī)制的喂狗方式是,hrtimer每次執(zhí)行時(shí)都會(huì)對(duì)一個(gè)變量進(jìn)行加一。
關(guān)于softlockup和hardlockup檢測(cè)機(jī)制的具體原理實(shí)現(xiàn)和應(yīng)用場(chǎng)景,我最近發(fā)布了一個(gè)視頻“Linux常見鎖和lockup檢查機(jī)制" 包含了從實(shí)現(xiàn)原理(linux內(nèi)核代碼層)和原理驗(yàn)證(使用ftrace調(diào)試手段)、樣例代碼、動(dòng)手模擬實(shí)驗(yàn),可以全方位理解softlockup/hardlockup.