io hang linux 原理,Linux Hang Task 简介

Linux Hang Task 简介

2018-06-30 Saturday

长期以来,处于 D 状态的进程都是让人比较烦恼的问题,此时不能接收信号,不能 kill 掉,用户对此基本是无能为力,而且也很难知道发生的原因,一般来说只能重启服务器恢复。

正常来说 D 状态的任务只有在 IO 操作时会有,而且会很快完成,只有在极端的异常场景下才会出现问题,例如磁盘损坏、NFS 的 bug 等等,不过如果驱动写的完善的话,一般会增加超时机制,原则上不会出现永久的 D 状态进程。

也就是说,只有在内核驱动不合理的时候可能会导致进程长期处于 D 状态,无法唤醒,类似于死锁状态。

简介

针对这种情况,内核在 3.10.0 版本之后提供了 hung task 机制,用来检测系统中长期处于 D 状体的进程,如果存在,则打印相关警告和进程堆栈。

如果配置了 hung_task_panic ,则会直接发起 panic 操作,然后结合 kdump 可以搜集到相关的 vmcore 文件,用于定位分析。

其基本原理也很简单,系统启动时会创建一个内核线程 khungtaskd,定期遍历系统中的所有进程,检查是否存在处于 D 状态且超过 120s 的进程,如果存在,则打印相关警告和进程堆栈,并根据参数配置决定是否发起 panic 操作。

配置项

与 hung task 相关的配置项主要有如下几个,可以直接通过 echo 'xx' > file 的方式进行修改。

----- 处于D状态的超时时间,默认是120s

$ cat /proc/sys/kernel/hung_task_timeout_secs

----- 发现hung task之后是否触发panic操作

$ cat /proc/sys/kernel/hung_task_panic

----- 每次检查的进程数

$ cat /proc/sys/kernel/hung_task_check_count

----- 为了防止日志被刷爆,设置最多的打印次数

$ cat /proc/sys/kernel/hung_task_warnings

示例

INFO: task ps:211718 blocked for more than 120 seconds.

"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.

[46953.928424] ps D ffffffff816ac3a9 0 211718 211717 0x00000080

[46953.928426] Call Trace:

[46953.928429] [] schedule+0x29/0x70

[46953.928431] [] rwsem_down_read_failed+0xf5/0x170

[46953.928434] [] call_rwsem_down_read_failed+0x18/0x30

[46953.928439] [] down_read+0x20/0x30

[46953.928442] [] __access_remote_vm+0x51/0x1f0

[46953.928445] [] access_remote_vm+0x1f/0x30

[46953.928448] [] proc_pid_cmdline_read+0x193/0x560

[46953.928452] [] vfs_read+0x9f/0x170

[46953.928456] [] SyS_read+0x7f/0xe0

[46953.928460] [] system_call_fastpath+0x1c/0x21

内核分析

在内核启动时会在 hung_task_init() 函数中启动一个内核线程。

hung_task_init()

|-atomic_notifier_chain_register() 注册panic通知链,在发生panic时执行相关的操作

|-kthread_run() 启动一个内核线程,处理函数为watchdog(),线程名为khungtaskd

|-watchdog()

|-set_user_nice() 设置为普通优先级,不影响业务运行

|-schedule_timeout_interruptible() 设置内核定时器,默认为120s

|-atomic_xchg() 检测是否需要运行

|-check_hung_uninterruptible_tasks() 真正执行检测

|-check_hung_task()

在 check_hung_uninterruptible_tasks() 函数中会设置每次检查的进程数,以及批量检查的上限 HUNG_TASK_BATCHING 。

打印调试信息的时候需要在编译时打开 CONFIG_DEBUG_MUTEXS 开关。

内核通知链

在 Linux 内核中,各子系统之间有很强的关联关系,例如某些子系统可能对其它子系统产生的事件感兴趣。

为了在各个子系统之间发送信息,Linux 内核引入了通知链技术,只在内核的子系统之间使用,而不能够在内核和用户空间进行事件的通知。

如果喜欢这里的文章,而且又不差钱的话,欢迎打赏个早餐 ^_^

支付宝打赏

微信打赏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IO stream在Linux中的工作原理可以通过NIOIO多路复用来解释。NIO是一种基于事件驱动的IO模型,它通过使用非阻塞IO和选择器(Selector)来实现。非阻塞IO允许程序在等待IO操作完成时继续执行其他任务,而选择器则可以同时监视多个通道的IO事件。当一个通道有IO事件发生时,选择器会通知程序进行相应的处理。这种模型可以提高系统的并发性能和响应能力。\[1\] 另外,Linux中还引入了select和epoll系统调用来查询IO文件描述符的就绪状态。通过这些系统调用,一个用户进程可以监视多个文件描述符,一旦某个描述符就绪,内核就会将其就绪状态返回给用户进程,用户进程可以根据就绪状态进行相应的IO操作。这种方式被称为IO多路复用,也是一种经典的Reactor模式实现。在Java中,Selector类就是基于这种模型实现的。\[3\] 总结起来,IO stream在Linux中的工作原理可以通过NIOIO多路复用来解释。NIO使用非阻塞IO和选择器来实现事件驱动的IO,而IO多路复用则通过select和epoll系统调用来查询IO文件描述符的就绪状态。这些机制都可以提高系统的并发性能和响应能力。 #### 引用[.reference_title] - *1* *3* [io的基本原理-nio](https://blog.csdn.net/weixin_45904404/article/details/128999221)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [linux下的四种IO模型](https://blog.csdn.net/weixin_46060137/article/details/121768602)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值