Linux看门狗是一个守护进程,主要用于监视系统运行状态,并在系统遇到异常情况或死机时自动重启系统。该功能广泛应用于计算机、嵌入式设备等领域,对于保障系统的可靠性和稳定性有着重要作用。
10多年的新城网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。网络营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整新城建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“新城网站设计”,“新城网站推广”以来,每个客户项目都认真落实执行。
本文将以一个简单的看门狗代码演示为例,介绍Linux看门狗的实现原理和使用方法。
1. 实现原理
Linux看门狗的实现原理非常简单,主要有以下几个步骤:
1)设定看门狗定时器。看门狗定时器的作用是定时检查系统的运行状态,如果系统正常运行,则重置看门狗计时器;如果系统异常或死机,则看门狗计时器超时,触发重启系统的操作。
2)初始化看门狗设备。在Linux系统启动时,需要通过驱动程序初始化看门狗设备,并将看门狗定时器设置为一个合适的值,以便于检测系统异常情况的发生。
3)启动看门狗守护进程。看门狗守护进程在后台运行,定期检查系统运行状态,并根据情况进行系统重启等操作。
2. 代码演示
下面是一个简单的看门狗代码演示,主要包括看门狗设备的初始化和看门狗守护进程的实现。
(1)看门狗设备的初始化
#include
#include
#include
#include
#include
int mn()
{
int fd;
// 打开看门狗设备,获取文件句柄
fd = open(“/dev/watchdog”, O_WRON);
if (fd
perror(“watchdog”);
return 1;
}
// 设置看门狗定时器为30s
ioctl(fd, WDIOC_SETTIMEOUT, 30);
// 关闭看门狗设备
close(fd);
return 0;
}
在上述代码中,首先通过open()函数打开/dev/watchdog设备文件,获取到该文件的文件句柄。然后使用ioctl()函数设置看门狗定时器为30秒。最后使用close()函数关闭看门狗设备。
(2)看门狗守护进程的实现
#include
#include
#include
#include
#include
int mn()
{
int fd;
// 打开看门狗设备,获取文件句柄
fd = open(“/dev/watchdog”, O_WRON);
if (fd
perror(“watchdog”);
return 1;
}
while (1) {
// 写入看门狗喂狗指令
ioctl(fd, WDIOC_KEEPALIVE, 0);
// 等待一段时间,等待看门狗定时器的超时
sleep(1);
}
// 关闭看门狗设备
close(fd);
return 0;
}
在上述代码中,首先通过open()函数打开/dev/watchdog设备文件,获取到该文件的文件句柄。然后在while循环中使用ioctl()函数写入喂狗指令,以保证看门狗定时器不会超时。最后使用close()函数关闭看门狗设备。
3. 使用方法
将上述两个程序编译成可执行文件,然后在Linux系统启动时,运行看门狗守护进程即可。例如,可以在/etc/rc.local文件中添加如下命令:
nohup /path/to/watchdog_daemon &
其中,/path/to/watchdog_daemon为看门狗守护进程可执行文件的路径。
在运行时,可以通过ps -ef | grep watchdog命令查看看门狗守护进程的运行情况。如果看门狗守护进程正常运行,说明系统正常;如果看门狗守护进程停止运行,说明系统遇到了异常情况,此时看门狗定时器将在一定时间内超时,自动触发系统重启的操作。
4.
成都网站建设公司-创新互联,建站经验丰富以策略为先导10多年以来专注数字化网站建设,提供企业网站建设,高端网站设计,响应式网站制作,设计师量身打造品牌风格,热线:028-86922220Linux Kernel BUG:soft lockup CPU#1 stuck分析
1.线上内核bug日志
kernel: Deltaway too big!ts=write stamp =377
kernel:
kernel:WARNING: at kernel/trace/ring_buffer.c:1988 rb_reserve_next_event+0x2ce/岩衫0x370()(Not tainted)
kernel:Hardware name: ProLiant DL360 G7
kernel:Modules linked in: fuse ipv6 power_meter bnx2 sg microcode serio_raw iTCO_wdtiTCO_vendor_support hpilo hpwdt i7core_edac edac_core shpchp ext4 mbcache jbd2sd_mod crc_t10dif hpsa radeon ttm drm_kms_helper drm i2c_algo_bit i2c_coredm_mirror dm_region_hash dm_log dm_mod
kernel: Pid:5483, comm: master Not tainted 2.6.32-220.el6.x86_64 #1
kernel: CallTrace:
kernel: ? warn_slowpath_common+0x87/0xc0
kernel: ? warn_slowpath_null+0x1a/0x20
kernel: ? rb_reserve_next_event+0x2ce/0x370
kernel: ? ring_buffer_lock_reserve+0xa2/0x160
kernel: ? trace_buffer_lock_reserve+0x2c/0x70
kernel: ? trace_current_buffer_lock_reserve+0x16/0x20
kernel: ? ftrace_raw_event_hrtimer_cancel+0x4e/厅枣局0xb0
kernel: ? hrtimer_try_to_cancel+0xba/0xd0
kernel: ? do_setitimer+0xd4/0x220
kernel: ? alarm_setitimer+0x3a/0x60
kernel: ? sys_alarm+0xe/0x20
kernel: ? tracesys+0xd9/0xde
kernel: ——
abrt-dump-oops: Reported 1 kernel oopses to Abrt
kernel: BUG: softlockup – CPU#11 stuck fors!
kernel:Modules linked in: fuse ipv6 power_meter bnx2 sg microcode serio_raw iTCO_wdtiTCO_vendor_support hpilo hpwdt i7core_edac edac_core shpchp ext4 mbcache jbd2sd_mod crc_t10dif hpsa radeon ttm drm_kms_helper drm i2c_algo_bit i2c_coredm_mirror dm_region_hash dm_log dm_mod
kernel: CPU 11
kernel:Modules linked in: fuse ipv6 power_meter bnx2 sg microcode serio_raw iTCO_wdtiTCO_vendor_support hpilo hpwdt i7core_edac edac_core shpchp ext4 mbcache jbd2sd_mod crc_t10dif hpsa radeon ttm drm_kms_helper drm i2c_algo_bit i2c_coredm_mirror dm_region_hash dm_log dm_mod
kernel:
kernel: Pid:5492, comm: qmgr Tainted: G W— 2.6.32-220.el6.x86_64 #1 HPProLiant DL360 G7
kernel: RIP:0010: do_setitimer+0x1d0/0x220
kernel: RSP:0018:ffff88080a661ef8 EFLAGS:
kernel: RAX:ffff88080b175a08 RBX: ffff88080a661f18 RCX:000
kernel: RDX:00 RSI:082 RDI: ffff88080c8c4c40
kernel: RBP:ffffffff8100bc0e R08:000 R09: 0099d7270e01c3f1
kernel: R10:00 R11:246 R12: ffffffff810ef9a3
kernel: R13:ffff88080a661e88 R14:000 R15: ffff88080a65a544
kernel: FS:00007f10b245f7c0(0000) GS:ffff88083c4a0000(0000) knlGS:00
kernel: CS:0010 DS: 0000 ES: 0000 CR0:03b
kernel: CR2:00007ffCR3:a80b000 CR4:6e0
kernel: DR0:00 DR1:000 DR2:000
kernel: DR3:00 DR6:ffff0ff0 DR7:400
kernel:Process qmgr (pid: 5492, threadinfo ffff88080a660000, task ffff)
kernel: Stack:
kernel:00007f10b323deff10b248eadf10b26d0ff10b248ede0
kernel: ffff88080a661f68 ffffffff8106f88a000000
kernel:14cf423d000000
kernel: CallTrace:
kernel: ? alarm_setitimer+0x3a/0x60
kernel: ? sys_alarm+0xe/0x20
kernel: ? tracesys+0xd9/0xde
kernel: Code:89 ef e83 3db49 8bfffb 66 0f 1fc0 e9 64 fe ff ff49 8bc7 80 d
kernel: CallTrace:
kernel: ? do_setitimer+0x209/0x220
kernel: ? alarm_setitimer+0x3a/0x60
kernel: ? sys_alarm+0xe/0x20
kernel: ? tracesys+0xd9/0xde
abrt-dump-oops: Reported 1 kernel oopses to Abrt
2.内核软死锁(soft lockup)bug原因分析
Soft lockup名称解释:所谓,soft lockup就是说,这个bug没有让系统彻底死机,但是若干个进程(或者kernel thread)被锁死在了某个状态(一般在内核区域),很多情况下这个是由于内核锁的使用的问题。
Linux内核对于每一个cpu都有一个监控进程,在技术界这个叫做watchdog(看门狗)。通过ps –ef | grep watchdog能够看见,进程名称大概是watchdog/X(数字:cpu逻辑编号1/2/3/4之类的)。这个进程或者线程每一秒钟运行一次,否则会睡眠和待机。这个进程运行会收集每一个cpu运行时使用数据的时间并且存放到属于每个cpu自己的内核数据结构。在内核中有很多特定的中断函数。这些中断函数会调用soft lockup计数,他会使用当前的时间戳与特定(对应的)cpu的内核数据结构中保存的时间对比,如果发现当前的时间戳比对应cpu保存的时间大于设定的阀值,他就假设监测进程或看门狗线程在一个相当可观的时间还没有执。Cpu软锁为什么会产生,是怎么产生的?如果linux内核是经过精心设计安排的CPU调度访问,那么怎么会产生cpu软死锁?那么只能说由于用户开发的或者第三方软件引入,看我们服务器内核panic的原因就是qmgr进程引起。因为每一个无限的循环都会一直有一个cpu的执行流程(qmgr进程示一个后台邮件的消息队列服务进程),并且拥有一定的优先级。Cpu调度器调度一个驱动程序来运行,如果这个驱动程序有问题并且没有被检测到,那么这个驱动程序将会暂用cpu的很长时间。根据前面的描述,看门狗进程会抓住(catch)这一点并且抛出一个软死锁(soft lockup)错误。软死锁会挂起cpu使你的系统不可用。
如果是用户空间的进程或线程引起的问题backtrace是不会有内容的,如果内核线程那么在soft lockup消息中会显示出backtrace信息。
3.根据linux内核源码分析错误
根据我们之一部分内核抛出的错误信息和call trace(linux内核的跟踪子系统)来分析产生的具体原因。
首先根据我们的centos版本安装相应的linux内核源码,具体步骤如下:
(1)下载源码的rpm包kernel-2.6.32-220.17.1.el6.src.rpm
(2)安装相应的依赖库,命令:yuminstall rpm-build redhat-rpm-config asciidoc newt-devel
(3)安装源码包:rpm -ikernel-2.6.32-220.17.1.el6.src.rpm
(4)进入建立源码的目录:cd~/rpmbuild/SPECS
(5)建立生成源码目录:rpmbuild-bp –target=`uname -m` kernel.spec
下面开始真正的根据内核bug日志分析源码:
(1)之一阶段内核错误日志分析(时间在Dec 4 14:03:34这个阶段的日志输出代码分析,其实这部分代码不会导致cpu软死锁,主要是第二阶段错误日志显示导致cpu软死锁)
我们首先通过日志定位到相关源代码:看下面日志:Dec 4 14:03:34 BP-YZH-1-xxxx kernel: WARNING: atkernel/trace/ring_buffer.c:1988 rb_reserve_next_event+0x2ce/0x370() (Not tainted)
根据日志内容我们可以很容易的定位到kernel/trace/ring_buffer.c这个文件的1988行代码如下:WARN_ON(1)。
先简单解释一下WARN_ON的作用:WARN_ON只是打印出当前栈信息,不会panic。所以会看到后面有一大堆的栈信息。这个宏定义如下:
#ifndef WARN_ON
#defineWARN_ON(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on))\
__WARN();\
unlikely(__ret_warn_on); \
})
#endif
这个宏很简单保证传递进来的条件值为0或者1(两次逻辑非操作的结果),然后使用分支预测技术(保证执行概率大的分支紧邻上面的指令)判断是否需要调用__WARN()宏定义。如果满足条件执行了__WARN()宏定义也接着执行一条空指令;。上面调用WARN_ON宏是传递的1,所以会执行__WARN()。下面继续看一下__WARN()宏定义如下:
#define __WARN()warn_slowpath_null(__FILE__,__LINE__)
从接下来的call trace信息中我们也确实发现调用了warn_slowpath_null这个函数。通过在linux内核源代码中搜索这个函数的实现,发现在panic.c(内核恐慌时的相关功能实现)中实现如下:
voidwarn_slowpath_null(const char *file, int line)
{
warn_slowpath_common(file, line,__builtin_return_address(0),
TAINT_WARN, NULL);
}
EXPORT_SYMBOL(warn_slowpath_null);//都出这个符号,让其他模块可以使用这个函数
同样的我们看到了warn_slowpath_common这个函数,而在call trace当中这个函数在warn_slowpath_null函数之前打印出来,再次印证了这个流程是正确的。同样在panic.c这个文件中我发现了warn_slowpath_common这个函数的实现如下:
static voidwarn_slowpath_common(const char *file, int line, void *caller,
unsigned taint, struct slowpath_args *args)
{
const char *board;
printk(KERN_WARNING “\n”);
printk(KERN_WARNING “WARNING: at %s:%d %pS()(%s)\n”,
file, line, caller, print_tainted());
board = dmi_get_system_info(DMI_PRODUCT_NAME);//得到dmi系统信息
if (board)
printk(KERN_WARNING “Hardware name:%s\n”, board);//通过我们的日志信息可以发现我们硬件名称是ProLiant DL360 G7
if (args)
vprintk(args->fmt, args->args);
print_modules();//打印系统模块信息
dump_stack();//dump信息输出(call trace开始)
print_oops_end_marker();//打印oops结束
add_taint(taint);
}
分析这个函数的实现不难发现我们的很多日志信息从这里开始输出,包括打印一些系统信息,就不继续深入分析了(请看代码注释,里面调用相关函数打印对应信息,通过我分析这些函数的实现和我们的日志信息完全能够对应,其中dump_stack是与cpu体系结构相关的,我们的服务器应该是属于x86体系)。这里在继续分析一下dump_stack函数的实现,因为这个是与cpu体系结构相关的,而且这个函数直接反应出导致内核panic的相关进程。这个函数实现如下:
/*
* The architecture-independent dump_stackgenerator
*/
void dump_stack(void)
{
unsigned long stack;
printk(“Pid: %d, comm: %.20s %s %s %.*s\n”,
current->pid, current->comm,print_tainted(),
init_utsname()->release,
linux 看门狗代码示例的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux 看门狗代码示例,Linux实例:看门狗代码演示,如何linux内核报告问题的信息别忘了在本站进行查找喔。
成都创新互联科技公司主营:网站设计、网站建设、小程序制作、成都软件开发、网页设计、微信开发、成都小程序开发、网站制作、网站开发等业务,是专业的成都做小程序公司、成都网站建设公司、成都做网站的公司。创新互联公司集小程序制作创意,网站制作策划,画册、网页、VI设计,网站、软件、微信、小程序开发于一体。
当前标题:Linux实例:看门狗代码演示(linux看门狗代码示例)
文章链接:http://www.shufengxianlan.com/qtweb/news49/42199.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联