首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往
50 篇文章
1
混部之殇-论云原生资源隔离技术之CPU隔离(一)
2
腾讯TencentOS 十年云原生的迭代演进之路
5
一次内核hung task分析
6
容器因内存频繁OOM而引发的内核“血案”
7
NFSv4客户端hung住的BUG,您解决了吗?
8
nfs不同版本的挂载与解析
9
(好文重发)朴英敏:用crash工具分析Linux内核死锁的一次实战
10
内核问题解决方法记录
11
blocked for more than 120 seconds
12
记一次Linux主机内存脏数据引发的NameNode故障
13
​[linux][memory]cgroup回收内存对虚拟机的影响分析
14
docker cgroup 技术之memory(首篇)
15
[linux][memory] 内存回收
16
Linux内核理解 Memory barrier(内存屏障)
17
Linux内核27-优化和内存屏障
18
谢宝友:深入理解 Linux RCU 从硬件说起之内存屏障
19
谢宝友:深入理解 RCU 之概念
20
聊聊 Linux 上软件实现的“交换机” - Bridge!
21
谈谈 Linux 假死现象
22
宋宝华: 数据库为什么有可能喜欢Linux AIO(异步I/O)?
23
深入理解Linux内核之脏页跟踪
24
Iowait的成因、对系统影响及对策
25
打通IO栈:一次编译服务器性能优化实战
26
浅谈Linux dirty data配置
27
write文件一个字节后何时发起写磁盘IO?
28
深入理解 Linux的 I/O 系统
29
深入理解Linux 的Page Cache
30
深入理解Linux文件系统之文件系统挂载(上)
31
深入理解Linux文件系统之文件系统挂载(下)
32
【线上故障】通过系统日志分析和定位
33
实战案例分享:根据 JVM crash 日志定位和分析问题
34
Linux系统安全 | Linux日志分析和管理
35
如何快速处理线上故障
36
面试-线上故障如何排查
37
Linux内核Crash分析
38
内核timer crash debug思路
39
一次解决Linux内核内存泄漏实战全过程
40
Linux Kernel模块内存泄露的一种查找思路
41
linux系统奔溃之vmcore:kdump 的亲密战友 crash
42
crash浅析tasklist_lock与进程释放
43
Linux OOM机制分析
44
cgroup oom引发Pod重建问题分析
45
workqueue相关数据结构在内核crash分析中的实战应用
46
Linux设备驱动workqueue(工作队列)案例实现
47
Linux内核中的软中断、tasklet和工作队列具体解释
48
扒开 Linux 中断的底裤之 workqueue
49
Linux系统驱动之GIC驱动程序对中断的处理流程
50
Linux系统驱动之链式中断控制器驱动程序编写

一次内核hung task分析

1 简介

今天发现突然有一台主机无缘无故死机了,于是翻看了/var/log/message日志,发现提示: echo 0 > /proc/sys/kernel/hung_task_timeout_secs;

我们知道进程等待IO时,经常处于D状态,即TASK_UNINTERRUPTIBLE状态,处于这种状态的进程不处理信号,所以kill不掉,如果进程长期处于D状态,那么肯定不正常,原因可能有二: 1)IO路径上的硬件出问题了,比如硬盘坏了(只有少数情况会导致长期D,通常会返回错误); 2)内核自己出问题了。 这种问题不好定位,而且一旦出现就通常不可恢复,kill不掉,通常只能重启恢复了。 内核针对这种开发了一种hung task的检测机制,基本原理是:定时检测系统中处于D状态的进程,如果其处于D状态的时间超过了指定时间(默认120s,可以配置),则打印相关堆栈信息,也可以通过proc参数配置使其直接panic。

完整日志如下:

2 原因

默认情况下, Linux会最多使用40%的可用内存作为文件系统缓存。当超过这个阈值后,文件系统会把将缓存中的内存全部写入磁盘, 导致后续的IO请求都是同步的。将缓存写入磁盘时,有一个默认120秒的超时时间。

出现上面的问题的原因是IO子系统的处理速度不够快,不能在120秒将缓存中的数据全部写入磁盘。IO系统响应缓慢,导致越来越多的请求堆积,最终系统内存全部被占用,导致系统失去响应。

这个Linux延迟写机制带来的问题,并且在主机内存越大时,出现该问题的可能性更大。这篇文章也提到This is a know bug。

代码语言:javascript
复制
This is a know bug. By default Linux uses up to 40% of the available memory for file system caching. After this mark has been reached the file system flushes all outstanding data to disk causing all following IOs going synchronous. For flushing out this data to disk this there is a time limit of 120 seconds by default. In the case here the IO subsystem is not fast enough to flush the data withing 120 seconds. This especially happens on systems with a lof of memory.

The problem is solved in later kernels and there is not “fix” from Oracle. I fixed this by lowering the mark for flushing the cache from 40% to 10% by setting “vm.dirty_ratio=10” in /etc/sysctl.conf. This setting does not influence overall database performance since you hopefully use Direct IO and bypass the file system cache completely.

链接:nfo-task-blocked-for-more-than-120-seconds

关于脏数据,有几个配置:

vm.dirty_background_ratio 是内存可以填充“脏数据”的百分比。这些“脏数据”在稍后是会写入磁盘的,pdflush/flush/kdmflush这些后台进程会稍后清理脏数据。举一个例子,我有32G内存,那么有3.2G的内存可以待着内存里,超过3.2G的话就会有后来进程来清理它。

那么总结起来,这个问题即因为:业务进程Appxxx出现了段错误,从而需要进行coredump的搜集,同时需要向业务进程发送信号使其终止运行,业务进程在处理信号,退出过程中,需要等coredump搜集完成,从而一直处于D状态,而因为业务进程占用的内存比较大导致收集时间比较长,超过了2分钟,所以出现了阻塞,触发hung task检测,但后来coredump收集完成后就自动恢复了。

vm.dirty_ratio 是绝对的脏数据限制,内存里的脏数据百分比不能超过这个值,如果超过,将强制刷写到磁盘。如果脏数据超过这个数量,新的IO请求将会被阻挡,直到脏数据被写进磁盘。这是造成IO卡顿的重要原因,但这也是保证内存中不会存在过量脏数据的保护机制。

vm.dirty_expire_centisecs 指定脏数据能存活的时间。在这里它的值是30秒。当 pdflush/flush/kdmflush 进行起来时,它会检查是否有数据超过这个时限,如果有则会把它异步地写到磁盘中。毕竟数据在内存里待太久也会有丢失风险。

vm.dirty_writeback_centisecs 指定多长时间 pdflush/flush/kdmflush 这些进程会起来一次;

3 io术语

3.1 页高速缓存

页高速缓存是Linux kernel使用的主要的磁盘缓存技术。磁盘高速缓存是一种软件机制,它允许系统把存放在磁盘上的一些数据保留在内存中,以便对那些数据的再次访问不再需要访问磁盘。

Kernel在读取磁盘时,如果数据页不再高速缓存当中,就会将读出的磁盘数据填充到页高速缓存当中。通过将数据页在高速缓存当中驻留,从而使进程再使用该页时不再需要访问磁盘。

Kernel在把一页数据写到磁盘之前,首先检查页是否已经在高速缓存当中,如果不在,首先会将页数据填充到高速缓存当中。更新到磁盘I/O的动作不是立即进行的,而是会有一点延时,从而使进程有机会对写入的数据进一步修改,这就是内核的延迟写操作。

3.2 脏数据同步

进程对页高速缓冲区中的数据修改之后,数据页被标记为”脏数据”,即把PG_Dirty标志置位。Linux系统允许对脏数据写入磁盘块设备的延迟操作,被认为是显著增加了系统I/O能力的一种机制。

在下列条件下,脏数据写入磁盘中:

1 . 页高速缓存空间不足;

2 . 变脏以来,太久没有过更新;

3 . 进程通过系统调用(sync(),fsync(),fdataasync())强行对快设备的更新同步到磁盘,Msync系统调用来将内存映射下的脏数据刷新到磁盘;

3.3 Pdflush

Pdflush内核线程负责定期扫描缓存中脏数据,并在合适时候将其更新到磁盘。定时器一般是500分之一秒,可以通过/proc/sys/vm/dirty_writeback_centisecs文件调整这个值。 Pdflush线程的个数是根据情况动态调整的:

1 . 至少有2个,最多有8个pdflush线程。(通过/proc/sys/vm/nr_pdflush_threads参数)可以修改这些变量的值。

2 . 如果最近1s内,没有空闲的pdflush线程,就创建新的。

3 . 如果pdflush的空闲时间超过了1s,就删除一个pdflush。

3.4 Buffer/cache

Cache - 全称page cache。当进程发起对磁盘的读写操作时,主要用来在内存中缓存磁盘中的数据,与磁盘的同步由pdflush负责。

Buffer – 全称block buffer。Block buffer中存放的是bio结构体数据。BIO 结构体是VFS和 block layer之间的接口。通俗的理解,Block buffer是page cache和磁盘驱动器之间打交道的一层缓存。

系统页高速缓存的使用情况可以通过buffer/cache的监控数据来分析。

从文件读写角度来看,buffer多用于缓存文件的管理信息,如目录位置,inode信息等。Cache缓存的是文件内容。

由于CPU不能直接处理外设上的数据,buffer用来标记那些文件的位置等描述信息。Cache主要目的是增加传输性能,用于缓存文件内容。

3.5 Direct I/O

有一些更复杂的程序(通常称为自缓存应用程序),更愿意自己控制I/O的传输过程(),通过将O_DIRECT标志位置位,I/O数据的传送便绕过了页高速缓存。 出于以下原因,系统页高速缓存技术是有害的:

1 . 处理页高速缓存的多余指令,降低了read(),write()的效率

2 . Read(),write()系统调用不是在磁盘和用户空间直接传送,而是分成两步:在磁盘和内核空间,>在内核空间到用户空间。 与页高速缓存相关的系统参数

3 . /proc/sys/vm/dirty_background_ratio 表示系统可用内存中,最高可用于存储 dirty 数据的百分比。The maximum of percentage of((cache+free)-mapped)。缺省10%。

4 . /proc/sys/vm/dirty_ratio 表示进程产生的脏数据到达系统整体内存的百分比,此时触发pdflush进程把数据回写到磁盘。缺省设置40.

5 . /proc/sys/vm/dirty_expire_centisecs 表示脏数据在内存中驻留超过该值,pdflush会将该数据回写到磁盘。缺省是3000。

6 . /proc/sys/vm/dirty_writeback_centisecs 表示pdflush周期性间隔多久处理脏数据回写。

4 调优

我们可以从以下思路进行调优:

  1. 减少脏数据的比例,避免刷写超时
  2. 减小脏数据在内存中的存放时间,避免积少成多

修改相应参数

临时修改

代码语言:javascript
复制
# sysctl -w vm.dirty_ratio=10
# sysctl -w vm.dirty_background_ratio=5
# sysctl -p

永久修改

代码语言:javascript
复制
#vi /etc/sysctl.conf
写入
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10

sysctl -p

5 参考

下一篇
举报
领券