当前位置:网站首页>kernel hung_task死锁检测机制原理实现
kernel hung_task死锁检测机制原理实现
2022-08-04 22:50:00 【szembed】
1、实现原理分析
Linux的进程存在多种状态,可在include/linux/sched.h中查看。
-
/* Used in tsk->state: */
-
#define TASK_RUNNING 0x0000
-
#define TASK_INTERRUPTIBLE 0x0001
-
#define TASK_UNINTERRUPTIBLE 0x0002
-
#define __TASK_STOPPED 0x0004
-
#define __TASK_TRACED 0x0008
-
/* Used in tsk->exit_state: */
-
#define EXIT_DEAD 0x0010
-
#define EXIT_ZOMBIE 0x0020
-
#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
-
/* Used in tsk->state again: */
-
#define TASK_PARKED 0x0040
-
#define TASK_DEAD 0x0080
-
#define TASK_WAKEKILL 0x0100
-
#define TASK_WAKING 0x0200
-
#define TASK_NOLOAD 0x0400
-
#define TASK_NEW 0x0800
-
#define TASK_STATE_MAX 0x1000
-
-
/* Convenience macros for the sake of set_current_state: */
-
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
-
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
-
#define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED)
-
-
#define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)
-
-
/* Convenience macros for the sake of wake_up(): */
-
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
-
-
/* get_task_state(): */
-
#define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \
-
TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \
-
__TASK_TRACED | EXIT_DEAD | EXIT_ZOMBIE | \
-
TASK_PARKED)
其中有一种状态等待为TASK_UNINTERRUPTIBLE,称为D状态,处于该种状态下进程不接收信号,只能通过wake_up唤醒。处于这种状态的情况有很多,例如mutex锁就可能会设置进程于该状态,down信号量也有可能使进程处于该状态
-
static noinline
void __sched
-
__mutex_lock_slowpath(
struct mutex *
lock)
-
{
-
__mutex_lock(
lock, TASK_UNINTERRUPTIBLE,
0, NULL, _RET_IP_);
-
}
-
static noinline
void __sched
__down(
struct semaphore *sem)
-
{
-
__down_common(sem,
TASK_UNINTERRUPTIBLE,
MAX_SCHEDULE_TIMEOUT);
-
}
有时候进程在等待某种IO资源就绪时(wait_event机制)会设置进程进入该状态。一般情况下,进程处于该状态的时间不会太久,但若IO设备出现故障或者出现进程死锁等情况,进程就可能长期处于该状态而无法再返回到TASK_RUNNING态。因此,内核为了便于发现这类情况设计出了hung task机制专门用于检测长期处于D状态的进程并发出告警。本文分析内核hung task机制的源码并给出改进建议。
本文基于linux kernel 5.13.6版本源码为例进行分析,源代码位于kernel/hung_task.c。监控时间间隔通常为120s,在defconfig中进行定义CONFIG_DEFAULT_HUNG_TASK_TIMEOUT
2、代码解析
实现并不是很复杂,接下来我们对关键代码进行走读。
hung_task_call_panic用来控制是否触发panic复位,该配置默认为true。
3、总结
D状态死锁一般在底层驱动开发的过程中比较常见,如果代码规模比较庞大的话对于开发人员来讲不太容易定位,linux内核提供的这种hung task机制,开发人员只需要根据这些输出的定位信息就可以快速的进行定位。
不足:原生的hung_task也有自己的不足之处,因为在实际的应用中,我们对于不能kill掉的守护进程还是有需求的,比如通信相关进程、维测相关进程等,因此要想兼容此场景,就需要对原生hung_task机制进行改造,有两种方式:在检测时可以对指定的进程进行检查,或者对指定的进程不做检查。
附:
常见的进程状态有哪些?
R 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
D 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
Z 是 Zombie 的缩写,它表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
S 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
I 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。
边栏推荐
猜你喜欢
随机推荐
Leaflets of three bouquet of roses
【论文笔记KDD2021】MixGCF: An Improved Training Method for Graph Neural Network-based Recommender Systems
One trick to cure pycharm DEBUG error UnicodeDecodeError: 'utf-8' codec can't decode
Service Mesh落地路径
【2020】【论文笔记】超表面:多功能和可编程——
阿里巴巴2022届秋招面试真题和答案!
【3D建模制作技巧分享】ZBrush模型如何添加不同材质
Deep Learning RNN Architecture Analysis
地面高度检测/平面提取与检测(Fast Plane Extraction in Organized Point Clouds Using Agglomerative Hierarchical Clu)
PAN3020 Sub-1G无线收发芯片
赶紧进来!!!教你C语言实现扫雷小游戏(文章最后有源码!!!)
the warmest home
【TCP/IP 五 ICMP】
得不到你的心,就用“分布式锁”锁住你的人
go语言的日志实现(打印日志、日志写入文件、日志切割)
Latex fast insert author ORCID
Will we still need browsers in the future?(feat. Maple words Maple language)
QT[一] 信号与槽
go语言的time包介绍
后排乘客不系安全带?事故瞬间被甩出