1.问题描述 最近搭建的一个linux最小系统在运行到241秒时在控制台自动打印如下图信息,并且以后每隔120秒打印一次。 仔细阅读打印信息发现关键信息是hung_task_timeout_secs,第一次遇到这样的问
1.问题描述最近搭建的一个linux最小系统在运行到241秒时在控制台自动打印如下图信息,并且以后每隔120秒打印一次。 仔细阅读打印信息发现关键信息是“hung_task_timeout_secs”,第一次遇到这样的问题,首先百度… 通过翻看多个网友的博客,发现这是linux kernel的一个bug。大家对这个问题的解释也都比较一致,摘抄一段:
翻译过来就是: 一般情况下,linux会把可用内存的40%的空间作为文件系统的缓存。当缓存快满时,文件系统将缓存中的数据整体同步到磁盘中。但是系统对同步时间有最大120秒的限制。如果文件系统不能在时间限制之内完成数据同步,则会发生上述的错误。这通常发生在内存很大的系统上。系统内存大,则缓冲区大,同步数据所需要的时间就越长,超时的概率就越大。 2.解决办法网友们提供的解决方案大致有3种,分别对3种方案的效果进行验证测试。 2.1 缩小文件系统缓存大小此种方案是降低缓存占内存的比例,比如由40%降到10%,这样的话需要同步到磁盘上的数据量会变小,IO写时间缩短,会相对比较平稳。 文件系统缓存的大小是由内核参数vm.dirty_ratio 和 vm.dirty_backgroud_ratio控制决定的。
通常情况下,vm.dirty_ratio的值要大于vm.dirty_background_ratio的值。 下面说一下修改这两个参数的流程及效果。 (1)首先查看系统当前的vm.dirty_ratio 和 vm.dirty_ background_ratio的值。 在shell命令行中输入如下指令:
由上图可知,当前环境下,vm.dirty_ratio=20 ,vm.dirty_ background_ratio=10。在此情况下,会出现上述问题。 (2)修改vm.dirty_ratio和vm.dirty_ background_ratio的值。 把vm.dirty_ratio修改为10 ,vm.dirty_background_ratio修改为5。 在命令行输入如下命令:
(3)查看修改是否成功。 在命令行输入(1)中的指令即可。 由上图可知,参数修改成功。 (4)使参数修改立即生效。 在命令行输入如下指令即可。
(5)观察测试结果。 经过以上操作,缩减文件系统缓存之后,上述问题成功解决。 2.2 修改系统IO调度策略Linux的IO共有三种调度器:CFQ、noop、deadline。每个调度器都有其优点。
Linux发行版的默认采用的是cfq调度器。此方案就是把cfq调度器修改为最简单的noop调度器。 下面说一下修改调度器的流程。 (1)查看当前采用的调度器。 在命令行中输入如下指令:
由内核返回信息可知,当前采用的是cfq调度器。 (2)修改调度器。 在命令行中输入如下指令:
(3)查看修改是否成功。 在命令行中输入如(1)的指令。 由内核返回信息可知,调度器修改成功。 调度器的修改是立即生效的,不必重启内核。 (4)观察测试结果。 修改完成后,让系统继续运行一段时间。上述问题依然存在。所以此方案对本文的案例不起作用。对于其他案例是否起作用需要自己按照上述方式测试才能得知。 2.3 取消120秒时间限制此方案就是不让系统有那个120秒的时间限制。文件系统把数据从缓存转到外存慢点就慢点,应用程序对此延时不敏感。就是慢点就慢点,我等着。实际上操作系统是将这个变量设为长整形的最大值。 下面说一下内核hung task检测机制由来。我们知道进程等待IO时,经常处于D状态,即TASK_UNINTERRUPTIBLE状态,处于这种状态的进程不处理信号,所以kill不掉,如果进程长期处于D状态,那么肯定不正常,原因可能有二: 1)IO路径上的硬件出问题了,比如硬盘坏了(只有少数情况会导致长期D,通常会返回错误); 2)内核自己出问题了。 这种问题不好定位,而且一旦出现就通常不可恢复,kill不掉,通常只能重启恢复了。 内核针对此种情况开发了一种hung task的检测机制,基本原理是:定时检测系统中处于D状态的进程,如果其处于D状态的时间超过了指定时间(默认120s,可以配置),则打印相关堆栈信息,也可以通过proc参数配置使其直接panic。 如何修改或者取消120秒的时间限值呢。120秒的时间限值由内存参数kernel.hung_task_timeout_secs决定的。直接像方案一那样修改此内核参数的值就可。如果kernel.hung_task_timeout_secs的值设置为0,那就是把此种设置为长整型的最大值。 下面说一下修改调度器的流程。 (1)查看当前hung_task_timeout_secs值。 在命令行中输入如下指令:
有内核返回信息,可知当前设置的hung_task超时时间为120秒。 (2)修改hung_task_timeout_secs值。 把hung_task_timeout_secs的值修改为0,在命令行中输入如下指令:
(3)查看修改是否成功。 在命令行输入(1)中的指令即可。 (4)使参数修改立即生效。 在命令行输入如下指令即可。
(5)观察测试结果。 经过以上操作,取消120秒时间限值之后,上述问题成功解决。 心得: 经过上边的测试,可知对与本案例缩减文件系统缓冲大小和取消120秒时间限值均可以解决问题。但是取消120秒的时间限值会允许系统不可切换任务的出现。综合考虑决定采用方案1,即缩减文件系统的缓冲区大小。 3.永久修改内核参数在上述方案中采用sysctl可以修改内核参数,但是这只是临时修改,上电重启后又会恢复回之前的参数。那么如何才能够永久修改内核参数呢? 可以修改系统信息配置文件sysctl.conf,此配置文件在/etc目录下。打开配置文件在最后添加如下两行代码:
保存后重启系统,查看配置是否成功。 如果系统没有sysctl.conf文件,就像我的最小linux系统一样,则可以自己创建sysctl.conf。 在/etc目录下,采用vi指令:vi sysctl.conf新建sysctl.conf文件,然后输入如下代码后保存退出。 重启之后查看vm.dirty_ratio和vm.dirty_background_ratio的值,发现又恢复成之前的了。 这是因为开机启动时系统没有读取sysctl.conf文件进行配置。可以通过修改启动文件来解决。 以我使用的linux系统为例,启动文件是/etc/init.d/rcS。采用指令vi /etc/init.d/rcS打开rcS文件,在最末尾添加如下代码:./sbin/sysctl -p 保存后退出。 reboot重启可以看到内核打印信息中有如下信息: 进入控制台后,查看vm.dirty_ratio和vm.dirty_background_ratio的值,可知内核参数永久修改成功。 |
2024-04-02
2024-02-26
2023-01-24
2024-09-30
2022-08-15