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. }