watchdog工作原理:

 

在系统运行以后也就启动了看门狗的计数器,看门狗就开始自动计数,如果到了一定的时间还不去复位看门狗, 那么看门狗计数器就会溢出从而引起看门狗中断,造成系统复位。所以在使用有看门狗的芯片时要注意复位看门狗。

 

看门狗有硬件和软件的。常见的硬件看门狗是PCI接口和USB接口,体积很小。

 

Linux 自带了一个 watchdog 的软件程序,用于监视系统的运行,它包括一个内核 watchdog module 和一个用户空间的 watchdog 程序。

 

内核 watchdog 模块

 

通过 /dev/watchdog 这个字符设备与用户空间通信。用户空间程序一旦打开 /dev/watchdog 设备, 就会导致在内核中启动一个 1分钟的定时器,此后,用户空间程序需要保证在 1分钟之内向这个设备写入数据,每次写 操作会导致重新设定定时器。如果用户空间程序在 1分钟之内没有写操作,定时器到期会导致一次系统 reboot 操作。

 

用户空间程序可通过关闭 /dev/watchdog 来停止内核中的定时器。

 

用户空间的 watchdog 守护进程:

在用户空间,还有一个叫做 watchdog 的守护进程,它可以定期对系统进行检测,包括:

 

* Is the process table full? * Is there enough free memory? * Are some files accessible? * Have some files changed within a given interval? * Is the average work load too high? * Has a file table overflow occurred? * Is a process still running? The process is specified by a pid file. * Do some IP addresses answer to ping? * Do network interfaces receive traffic? * Is the temperature too high? (Temperature data not always available.) * Execute a user defined command to do arbitrary tests.

 

如果某项检测失败,则可能导致一次 soft reboot (模拟一次 shutdown 命令的执行),它还可以通过 /dev/watchdog 来触发内核 watchdog 的运行。

 

内核级”watchdog”与用户空间的”watchdog”的主要区别是,内核态的”watchdog”抗干扰能力强,运行稳定。

 

 

例子1:

 

[cpp] view plain copy print ?


1. /*
2.  * Watchdog usage.
3.  * Author: Serval Li
4.  * Date: Jun 27th, 2012
5.  * */
6. #include <stdio.h> 
7. #include <string.h> 
8. #include <stdlib.h> 
9. #include <unistd.h> 
10. #include <sys/ioctl.h> 
11. #include <sys/types.h> 
12. #include <sys/stat.h> 
13. #include <fcntl.h> 
14.   
15. #include <signal.h> 
16.   
17. #include <linux/types.h> 
18. #include <linux/watchdog.h> 
19.   
20. int main(void)  
21. {  
22. int
23. int
24. char
25.   
26. if ((fd = open("/dev/watchdog", O_RDWR)) < 0) {  
27. "");  
28.                 exit(1);  
29.         }  
30.   
31.         ioctl(fd, WDIOC_GETTIMEOUT, &timeout);  
32. "Default timeout: %d\n", timeout);  
33.   
34.         timeout = 12;  
35. "Set timeout to %d\n", timeout);  
36.         ioctl(fd, WDIOC_SETTIMEOUT, &timeout);  
37.   
38.         ioctl(fd, WDIOC_GETTIMEOUT, &timeout);  
39. "New timeout: %d\n", timeout);  
40.   
41.         flag = fcntl(0, F_GETFL, 0);  
42.         flag |= O_NONBLOCK;  
43. if (fcntl(0, F_SETFL, flag) < 0) {      /* fgets no-block now */
44. "Set stdin to non-block fails.");  
45.                 exit(1);  
46.         }  
47.   
48. while
49.                 ioctl(fd, WDIOC_KEEPALIVE, 0);  
50. sizeof(cmd) - 1, stdin);  
51. if(strncmp(cmd, "stop", 4) == 0)  
52. goto
53.                 sleep(timeout / 2);  
54.         }  
55.   
56. stopwd:  
57. "V", 1);      /* This is "V", not "v"! */
58.         close(fd);  
59. "Close watchdog!");  
60.   
61. return
62. }

 例子2:

[cpp] view plain copy print ?

1. #include <stdio.h> 
2. #include <stdlib.h> 
3. #include <string.h> 
4. #include <sys/types.h> 
5. #include <sys/stat.h> 
6. #include <unistd.h> 
7. #include <fcntl.h> 
8. #include <sys/ioctl.h> 
9. #include <errno.h> 
10. #include <sys/time.h> 
11. #include <unistd.h> 
12. #include <time.h> 
13. #include <getopt.h> 
14. #include <sys/signal.h> 
15. #include <termios.h> 
16.   
17. struct
18. int options;   //options the card/driver supprots 19         
19. int firmware_version;  //firmcard version of the card
20. char identity[32];     //identity of the board 21
21.  };  
22.   
23. #define WATCHDOG_IOCTL_BASE 'W'
24. #define WDIOC_GETSUPPORT _IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
25. #define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
26. #define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) 27 
27. #define WDIOS_DISABLECARD 0x0001        /* Turn off the watchdog timer */
28. #define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */
29. #define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
30. #define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)
31.   
32. int Getch (void)   //无回显的从屏幕输入字符,来达到喂狗的目的
33.   
34. {  
35.   
36. int
37. struct termios oldt, newt;   //终端设备结构体
38. //获得终端属性
39.      newt = oldt;  
40. //设置无回显属性
41. //设置新的终端属性
42. //从键盘输入一个数据 
43. //恢复终端设备初始设置
44. return
45.   
46. }  
47. //suspend some seconds 
48. int zsleep(int
49.   
50. {  
51. long
52.      usec=1000*millisecond;  
53. //睡眠usec秒 
54. }  
55. int
56. {   
57. int
58. //open device file 
59. "/dev/watchdog",O_RDWR);   //打开看门狗设备
60. if(fd < 0)  
61.      {  
62. "device open fail\n");  
63. return
64.      }  
65. return
66. }  
67.   
68. int main(int argc,char
69. {  
70. int
71. int
72. char
73. struct
74. //打开终端看门狗设备 
75. //读板卡信息,但不常用 
76.   
77.       ioctl(fd,WDIOC_GETSUPPORT,&wi);  
78. "%d,%s\n",wi.options,wi.identity);  
79. //读看门狗溢出时间,默认是5s 
80.   
81. //重新设置时间为10s 
82.   
83.      i=5;  
84. "%d\n",ioctl(fd,WDIOC_SETTIMEOUT,&i));  
85. //读新的设置时间 
86.   
87. "%d\n",ioctl(fd,WDIOC_GETTIMEOUT,&i));  
88. "%d\n",i);   
89. //看门狗开始和停止工作,打开和关闭设备具有同样的功能
90.   
91. //关闭 
92.       i=WDIOS_DISABLECARD;  
93. "%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));  
94. //打开 
95.       i=WDIOS_ENABLECARD;  
96. "%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));  
97. while(1)  
98.      {  
99.            zsleep(100);  
100. if((c=Getch())!=27){  
101. //输入如果不是ESC,就喂狗,否则不喂狗,到时间后系统重启
102.   
103.                 ioctl(fd,WDIOC_KEEPALIVE,NULL);  
104. //write(fd,NULL,1);     //同样是喂狗
105.   
106.            }  
107.      }  
108. //关闭设备 
109. return
110. }

[cpp] view plain copy print ?

1. #include <stdio.h> 
2. #include <stdlib.h> 
3. #include <string.h> 
4. #include <sys/types.h> 
5. #include <sys/stat.h> 
6. #include <unistd.h> 
7. #include <fcntl.h> 
8. #include <sys/ioctl.h> 
9. #include <errno.h> 
10. #include <sys/time.h> 
11. #include <unistd.h> 
12. #include <time.h> 
13. #include <getopt.h> 
14. #include <sys/signal.h> 
15. #include <termios.h> 
16.   
17. struct
18. int options;   //options the card/driver supprots 19         
19. int firmware_version;  //firmcard version of the card
20. char identity[32];     //identity of the board 21
21.  };  
22.   
23. #define WATCHDOG_IOCTL_BASE 'W'
24. #define WDIOC_GETSUPPORT _IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
25. #define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
26. #define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) 27 
27. #define WDIOS_DISABLECARD 0x0001        /* Turn off the watchdog timer */
28. #define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */
29. #define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
30. #define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)
31.   
32. int Getch (void)   //无回显的从屏幕输入字符,来达到喂狗的目的
33.   
34. {  
35.   
36. int
37. struct termios oldt, newt;   //终端设备结构体
38. //获得终端属性
39.      newt = oldt;  
40. //设置无回显属性
41. //设置新的终端属性
42. //从键盘输入一个数据 
43. //恢复终端设备初始设置
44. return
45.   
46. }  
47. //suspend some seconds 
48. int zsleep(int
49.   
50. {  
51. long
52.      usec=1000*millisecond;  
53. //睡眠usec秒 
54. }  
55. int
56. {   
57. int
58. //open device file 
59. "/dev/watchdog",O_RDWR);   //打开看门狗设备
60. if(fd < 0)  
61.      {  
62. "device open fail\n");  
63. return
64.      }  
65. return
66. }  
67.   
68. int main(int argc,char
69. {  
70. int
71. int
72. char
73. struct
74. //打开终端看门狗设备 
75. //读板卡信息,但不常用 
76.   
77.       ioctl(fd,WDIOC_GETSUPPORT,&wi);  
78. "%d,%s\n",wi.options,wi.identity);  
79. //读看门狗溢出时间,默认是5s 
80.   
81. //重新设置时间为10s 
82.   
83.      i=5;  
84. "%d\n",ioctl(fd,WDIOC_SETTIMEOUT,&i));  
85. //读新的设置时间 
86.   
87. "%d\n",ioctl(fd,WDIOC_GETTIMEOUT,&i));  
88. "%d\n",i);   
89. //看门狗开始和停止工作,打开和关闭设备具有同样的功能
90.   
91. //关闭 
92.       i=WDIOS_DISABLECARD;  
93. "%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));  
94. //打开 
95.       i=WDIOS_ENABLECARD;  
96. "%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));  
97. while(1)  
98.      {  
99.            zsleep(100);  
100. if((c=Getch())!=27){  
101. //输入如果不是ESC,就喂狗,否则不喂狗,到时间后系统重启
102.   
103.                 ioctl(fd,WDIOC_KEEPALIVE,NULL);  
104. //write(fd,NULL,1);     //同样是喂狗
105.   
106.            }  
107.      }  
108. //关闭设备 
109. return
110. }

[cpp] view plain copy print ?

1. #include <stdio.h> 
2. #include <stdlib.h> 
3. #include <string.h> 
4. #include <sys/types.h> 
5. #include <sys/stat.h> 
6. #include <unistd.h> 
7. #include <fcntl.h> 
8. #include <sys/ioctl.h> 
9. #include <errno.h> 
10. #include <sys/time.h> 
11. #include <unistd.h> 
12. #include <time.h> 
13. #include <getopt.h> 
14. #include <sys/signal.h> 
15. #include <termios.h> 
16.   
17. struct
18. int options;   //options the card/driver supprots 19         
19. int firmware_version;  //firmcard version of the card
20. char identity[32];     //identity of the board 21
21.  };  
22.   
23. #define WATCHDOG_IOCTL_BASE 'W'
24. #define WDIOC_GETSUPPORT _IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
25. #define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
26. #define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) 27 
27. #define WDIOS_DISABLECARD 0x0001        /* Turn off the watchdog timer */
28. #define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */
29. #define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
30. #define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)
31.   
32. int Getch (void)   //无回显的从屏幕输入字符,来达到喂狗的目的
33.   
34. {  
35.   
36. int
37. struct termios oldt, newt;   //终端设备结构体
38. //获得终端属性
39.      newt = oldt;  
40. //设置无回显属性
41. //设置新的终端属性
42. //从键盘输入一个数据 
43. //恢复终端设备初始设置
44. return
45.   
46. }  
47. //suspend some seconds 
48. int zsleep(int
49.   
50. {  
51. long
52.      usec=1000*millisecond;  
53. //睡眠usec秒 
54. }  
55. int
56. {   
57. int
58. //open device file 
59. "/dev/watchdog",O_RDWR);   //打开看门狗设备
60. if(fd < 0)  
61.      {  
62. "device open fail\n");  
63. return
64.      }  
65. return
66. }  
67.   
68. int main(int argc,char
69. {  
70. int
71. int
72. char
73. struct
74. //打开终端看门狗设备 
75. //读板卡信息,但不常用 
76.   
77.       ioctl(fd,WDIOC_GETSUPPORT,&wi);  
78. "%d,%s\n",wi.options,wi.identity);  
79. //读看门狗溢出时间,默认是5s 
80.   
81. //重新设置时间为10s 
82.   
83.      i=5;  
84. "%d\n",ioctl(fd,WDIOC_SETTIMEOUT,&i));  
85. //读新的设置时间 
86.   
87. "%d\n",ioctl(fd,WDIOC_GETTIMEOUT,&i));  
88. "%d\n",i);   
89. //看门狗开始和停止工作,打开和关闭设备具有同样的功能
90.   
91. //关闭 
92.       i=WDIOS_DISABLECARD;  
93. "%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));  
94. //打开 
95.       i=WDIOS_ENABLECARD;  
96. "%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));  
97. while(1)  
98.      {  
99.            zsleep(100);  
100. if((c=Getch())!=27){  
101. //输入如果不是ESC,就喂狗,否则不喂狗,到时间后系统重启
102.   
103.                 ioctl(fd,WDIOC_KEEPALIVE,NULL);  
104. //write(fd,NULL,1);     //同样是喂狗
105.   
106.            }  
107.      }  
108. //关闭设备 
109. return
110. }