linux 内核死锁检测

lockdep是内核提供协助发现死锁问题的功能。

本文首先介绍何为lockdep,然后如何在内核使能lockdep,并简单分析内核lockdep相关代码。

最后构造不同死锁用例,并分析如何根据lockdep输出发现问题根源。

Lockdep介绍


死锁是指两个或多个进程因争夺资源而造成的互相等待的现象。
常见的死锁有如下两种:
递归死锁:中断等延迟操作中使用了锁,和外面的锁构成了递归死锁。
AB-BA死锁:多个锁因处理不当而引发死锁,多个内核路径上的所处理顺序不一致也会导致死锁。
Linux内核提供死锁调试模块Lockdep,跟踪每个锁的自身状态和各个锁之间的依赖关系,经过一系列的验证规则来确保锁之间依赖关系是正确的。


使能Lockdep


Lockdep检测的锁包括spinlock、rwlock、mutex、rwsem的死锁,锁的错误释放,原子操作中睡眠等错误行为。
在内核中配置路径为:Kernel hacking->Lock Debugging (spinlocks, mutexes, etc...)。

下面是lockcep内核选项及其解释:

CONFIG_DEBUG_RT_MUTEXES=y

检测rt mutex的死锁并自动报告死锁现场信息。

CONFIG_DEBUG_SPINLOCK=y

检测spinlock的未初始化使用等问题。配合NMI watchdog使用,能发现spinlock死锁。

CONFIG_DEBUG_MUTEXES=y

检测并报告mutex错误

CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y

检测wait/wound类型mutexslowpath测试。

CONFIG_DEBUG_LOCK_ALLOC=y

检测使用中的锁(spinlock/rwlock/mutex/rwsem)被释放或者使用中的锁被重新初始化或者在进程退出时持有锁。

CONFIG_PROVE_LOCKING=y

使内核能在死锁发生前报告死锁详细信息。参见/proc/lockdep_chains

Lock相关内核节点

/proc/sys/kernel/lock_stat------------------------置位则可以查看/proc/lock_stat统计信息,清楚则关闭lockdep统计信息。
/proc/sys/kernel/max_lock_depth--------------
/proc/sys/kernel/prove_locking
/proc/locks
/proc/lock_stat-------------------------------------关于锁的使用统计信息
/proc/lockdep---------------------------------------存在依赖关系的锁
/proc/lockdep_stats------------------------------存在依赖关系锁的统计信息
/proc/lockdep_chains----------------------------依赖关系锁链表
内核还提供了了Tracepoint协助发现锁的使用问题:/sys/kernel/debug/tracing/events/lock。
 测试spin_lock死锁
构造测试用例代码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>

static DEFINE_SPINLOCK(hack_spinA);
static DEFINE_SPINLOCK(hack_spinB);

void hack_spinAB(void)
{
    printk("hack_lockdep: A->B\n");
    spin_lock(&hack_spinA);
    spin_lock(&hack_spinB);
}

void hack_spinBA(void)
{
    printk("hack_lockdep: B->A\n");
    spin_lock(&hack_spinB);
}

static int __init lockdep_test_init(void)
{
    printk("figo: my lockdep module init");
    hack_spinAB();
    hack_spinBA();
    return 0;
}

static void __exit lockdep_test_exit(void)
{
    printk("goodbye\n");
}

MODULE_LICENSE("GPL"); //没有此句不然会造成内核污染,在加载模块时死锁检测机制会被迫关闭:Disabling lock debugging due to kernel taint
module_init(lockdep_test_init);
module_exit(lockdep_test_exit);

执行insmod data/lock.ko 后,(检测发生死锁时报错)控制台显示如下。
首先从死锁描述大概可以知道死锁类型。
然后详细介绍了产生死锁的点,这时就可以大概知道是哪个锁,有哪些地方调用导致了死锁。
接着是详细的发生死锁的backtrace,有助于分析死锁产生时的栈回溯。
figo: my lockdep module init
hack_lockdep:A->B
hack_lockdep:B->A
=============================================
[ INFO: possible recursive locking detected ] -----------------------------------------------检测到的死锁描述:递归死锁类型
4.0.0+ #87 Tainted: G O 
---------------------------------------------
insmod/658 is trying to acquire lock: --------------------------------------------------------死锁细节描述:欲持锁点和已持锁点
(hack_spinB){+.+...}, at: [<bf002030>] lockdep_test_init+0x30/0x3c [lock] ------------lockdep_test_init中调用hack_spinBA再次持有hack_spinB锁
but task is already holding lock:
(hack_spinB){+.+...}, at: [<bf000038>] hack_spinAB+0x38/0x3c [lock] -----------------hack_spinB已经在hack_spinAB函数中被持有
other info that might help us debug this: -----------------------------------------------------锁的其它补充信息
Possible unsafe locking scenario:
CPU0
----
lock(hack_spinB);
lock(hack_spinB);
*** DEADLOCK ***
May be due to missing lock nesting notation
2 locks held by insmod/658: -------------------------------------------------------------------进程共持有两个锁
#0: (hack_spinA){+.+...}, at: [<bf000030>] hack_spinAB+0x30/0x3c [lock]
#1: (hack_spinB){+.+...}, at: [<bf000038>] hack_spinAB+0x38/0x3c [lock]
stack backtrace:------------------------------------------栈回溯信息:可以看出从lockdep_test_init->_raw_spin_lock->lock_acquire的调用路径。
CPU: 0 PID: 658 Comm: insmod Tainted: G O 4.0.0+ #87
Hardware name: ARM-Versatile Express
[<c00171b4>] (unwind_backtrace) from [<c0012e7c>] (show_stack+0x20/0x24)
[<c0012e7c>] (show_stack) from [<c05ade10>] (dump_stack+0x8c/0xb4)
[<c05ade10>] (dump_stack) from [<c006b988>] (__lock_acquire+0x1aa4/0x1f64)
[<c006b988>] (__lock_acquire) from [<c006c55c>] (lock_acquire+0xf4/0x190)
[<c006c55c>] (lock_acquire) from [<c05b4ec8>] (_raw_spin_lock+0x60/0x98)
[<c05b4ec8>] (_raw_spin_lock) from [<bf002030>] (lockdep_test_init+0x30/0x3c [lock])
[<bf002030>] (lockdep_test_init [lock]) from [<c0008a28>] (do_one_initcall+0x9c/0x1e8)
[<c0008a28>] (do_one_initcall) from [<c05abf30>] (do_init_module+0x70/0x1c0)
[<c05abf30>] (do_init_module) from [<c00a4ddc>] (load_module+0x18b0/0x1f90)
[<c00a4ddc>] (load_module) from [<c00a55fc>] (SyS_init_module+0x140/0x150)
[<c00a55fc>] (SyS_init_module) from [<c000ec80>] (ret_fast_syscall+0x0/0x4c)
INFO: rcu_sched self-detected stall on CPU
0: (2099 ticks this GP) idle=5ed/140000000000001/0 softirq=13024/13024 fqs=1783 
(t=2100 jiffies g=-51 c=-52 q=22)
Task dump for CPU 0:
insmod R running 0 658 657 0x00000002
[<c00171b4>] (unwind_backtrace) from [<c0012e7c>] (show_stack+0x20/0x24)
[<c0012e7c>] (show_stack) from [<c0052874>] (sched_show_task+0x128/0x184)
[<c0052874>] (sched_show_task) from [<c0055dd0>] (dump_cpu_task+0x48/0x4c)
[<c0055dd0>] (dump_cpu_task) from [<c0082878>] (rcu_dump_cpu_stacks+0x9c/0xd4)
[<c0082878>] (rcu_dump_cpu_stacks) from [<c008665c>] (rcu_check_callbacks+0x640/0x968)
[<c008665c>] (rcu_check_callbacks) from [<c008b628>] (update_process_times+0x4c/0x74)
[<c008b628>] (update_process_times) from [<c009a1d4>] (tick_periodic+0x54/0xf8)
[<c009a1d4>] (tick_periodic) from [<c009a3d8>] (tick_handle_periodic+0x38/0x98)
[<c009a3d8>] (tick_handle_periodic) from [<c00164a4>] (twd_handler+0x40/0x50)
[<c00164a4>] (twd_handler) from [<c007dfc4>] (handle_percpu_devid_irq+0xd8/0x1dc)
[<c007dfc4>] (handle_percpu_devid_irq) from [<c0079a7c>] (generic_handle_irq+0x3c/0x4c)
[<c0079a7c>] (generic_handle_irq) from [<c0079dc4>] (__handle_domain_irq+0x6c/0xc4)
[<c0079dc4>] (__handle_domain_irq) from [<c0008740>] (gic_handle_irq+0x34/0x6c)
[<c0008740>] (gic_handle_irq) from [<c0013a44>] (__irq_svc+0x44/0x5c)
Exception stack(0xed5c9d18 to 0xed5c9d60)
9d00: 00000000 00010000
9d20: 0000ffff c02f3898 bf0001b0 c0b1d248 123cc000 00000000 0c99b2c5 00000000
9d40: 00000000 ed5c9d84 ed5c9d60 ed5c9d60 c0070cb4 c0070cb4 60000013 ffffffff
[<c0013a44>] (__irq_svc) from [<c0070cb4>] (do_raw_spin_lock+0xf0/0x1e0)
[<c0070cb4>] (do_raw_spin_lock) from [<c05b4eec>] (_raw_spin_lock+0x84/0x98)
[<c05b4eec>] (_raw_spin_lock) from [<bf002030>] (lockdep_test_init+0x30/0x3c [lock])
[<bf002030>] (lockdep_test_init [lock]) from [<c0008a28>] (do_one_initcall+0x9c/0x1e8)
[<c0008a28>] (do_one_initcall) from [<c05abf30>] (do_init_module+0x70/0x1c0)
[<c05abf30>] (do_init_module) from [<c00a4ddc>] (load_module+0x18b0/0x1f90)
[<c00a4ddc>] (load_module) from [<c00a55fc>] (SyS_init_module+0x140/0x150)
[<c00a55fc>] (SyS_init_module) from [<c000ec80>] (ret_fast_syscall+0x0/0x4c)
BUG: spinlock lockup suspected on CPU#0, insmod/658-----------------------------------------错误类型是spinlock,下面的backtrace和上面基本一致。
lock: hack_spinB+0x0/0xfffffedc [lock], .magic: dead4ead, .owner: insmod/658, .owner_cpu: 0-----------发生死锁的是hack_spinB
CPU: 0 PID: 658 Comm: insmod Tainted: G O 4.0.0+ #87
Hardware name: ARM-Versatile Express
[<c00171b4>] (unwind_backtrace) from [<c0012e7c>] (show_stack+0x20/0x24)
[<c0012e7c>] (show_stack) from [<c05ade10>] (dump_stack+0x8c/0xb4)
[<c05ade10>] (dump_stack) from [<c0070b2c>] (spin_dump+0x8c/0xd0)
[<c0070b2c>] (spin_dump) from [<c0070cd0>] (do_raw_spin_lock+0x10c/0x1e0)
[<c0070cd0>] (do_raw_spin_lock) from [<c05b4eec>] (_raw_spin_lock+0x84/0x98)
[<c05b4eec>] (_raw_spin_lock) from [<bf002030>] (lockdep_test_init+0x30/0x3c [lock])
[<bf002030>] (lockdep_test_init [lock]) from [<c0008a28>] (do_one_initcall+0x9c/0x1e8)
[<c0008a28>] (do_one_initcall) from [<c05abf30>] (do_init_module+0x70/0x1c0)
[<c05abf30>] (do_init_module) from [<c00a4ddc>] (load_module+0x18b0/0x1f90)
[<c00a4ddc>] (load_module) from [<c00a55fc>] (SyS_init_module+0x140/0x150)
[<c00a55fc>] (SyS_init_module) from [<c000ec80>] (ret_fast_syscall+0x0/0x4c)
 

CONFIG_LOCKDEP=y

整个Lockdep的总开关。参见/proc/lockdep/proc/lockdep_stats

CONFIG_LOCK_STAT=y

记锁持有竞争区域的信息包括等待时间、持有时间等等信息。参见/proc/lock_stat

CONFIG_DEBUG_LOCKDEP=y

会对Lockdep的使用过程中进行更多的自我检测,会增加很多额外开销。

CONFIG_DEBUG_ATOMIC_SLEEP=y

atomic section中睡眠可能造成很多不可预测的问题这些atomic section包括spinlock持锁、rcu读操作、禁止内核抢占部分、中断处理中等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/577304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu离线安装Docker

一、安装 docker 下载docker离线包 去官网下载docker 安装二进制包&#xff0c;选择适合自己的版本&#xff08;Docker version 20.10.8&#xff09;。 下载地址&#xff1a;https://download.docker.com/linux/static/stable/x86_64/文档名&#xff1a;docker-20.10.8.tgz用…

【Python】Python AI 绘画

本文我们将为大家介绍如何基于一些开源的库来搭建一套自己的 AI 作图工具。 需要使用的开源库为 Stable Diffusion web UI,它是基于 Gradio 库的 Stable Diffusion 浏览器界面 Stable Diffusion web UI GitHub 地址:GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable…

网络编程 day3

TCP多进程并发服务器 #include <stdio.h> #include "/home/ubuntu/head.h"#define IP "192.168.124.85" #define PORT 8888void handler(int sig) {while(waitpid(-1,NULL,WNOHANG)>0); }int main(int argc, const char *argv[]) {//回收僵尸进程…

[kubernetes]Kube-APIServer

API Server API Server是什么 提供集群管理的REST API接口&#xff0c;包括认证授权、数据校验以及集群状态变更等提供其他模块之间的数据交互和通信的枢纽&#xff08;其他模块通过API Server查询或修改数据&#xff0c;只有API Server才直接操作etcd&#xff09; 访问控制…

开源自托管导航页配置服务Dashy本地搭建结合内网穿透远程访问

开源自托管导航页配置服务Dashy本地搭建结合内网穿透远程访问 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 简介 Dashy 是一个开源的自托管的导航页配置服务&#xff0c;具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一…

Mongodb基础介绍与应用场景

NoSql 解决方案第二种 Mongodb MongoDB 是一款开源 高性能 无模式的文档型数据库 当然 它是NoSql数据库中的一种 是最像关系型数据库的 非关系型数据库 首先 最需要注意的是 无模式的文档型数据库 这个需要后面我们看到它的数据才能明白 其次是 最像关系型数据库的非关系型数据…

RK3588平台开发系列讲解(AI 篇)RKNN 数据结构详解

文章目录 一、rknn_sdk_version二、rknn_input_output_num三、rknn_tensor_attr四、rknn_perf_detail五、rknn_perf_run六、rknn_mem_size七、rknn_tensor_mem八、rknn_input九、rknn_output沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章主要讲解 RKNN 相关的数…

Autosar CAN开发02(入门Autosar)

Autosar架构 想起当时刚毕业进入公司之后&#xff0c;我的岗位是Autosar Bsw软件工程师。 看着这个什么“Autosar”&#xff0c;真的是一脸懵。 后来才知道&#xff0c;按照我的理解&#xff1a;Autosar就是一个软件架构。它分为ASW和BSW。ASW负责实现应用层功能&#xff08…

“React学习之旅:从入门到精通的点滴感悟“

在探索和学习React的过程中&#xff0c;我逐渐领悟到了前端开发的魅力与挑战。React&#xff0c;作为Facebook推出的开源JavaScript库&#xff0c;以其独特的思维方式和强大的功能&#xff0c;引领着前端开发的潮流。在这篇文章中&#xff0c;我将分享我的React学习心得&#x…

test assert-01-Google Truth 断言

Truth Truth 是用于Java测试的断言框架&#xff0c;灵感来自于FEST&#xff0c;并受到一些可扩展性需求的驱动&#xff0c;几乎完全由谷歌员工在业余时间编写&#xff0c;或者作为Java核心图书馆管理员的身份做出贡献。 作用 作为工程师&#xff0c;我们花费大部分的时间来阅…

《C++避坑神器·二十四》简单搞懂json文件的读写之根据键值对读写Json

c11 json解析库nlohmann/json.hpp文件整个代码由一个头文件组成 json.hpp&#xff0c;没有子项目&#xff0c;没有依赖关系&#xff0c;没有复杂的构建系统&#xff0c;使用起来非常方便。 json.hpp库在文章末尾下载 读写主要有两种方式&#xff0c;第一种根据键值对读写&…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Progress进度条组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Progress进度条组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Progress组件 进度条也是UI开发最常用的组件之一&#xff0c;进度条组件…

OpenAI换血大震动始末:“ChatGPT之父”奥特曼,缘何被“扫地出门”?

近期&#xff0c;AI业界发生了一场“大地震”。作为聊天机器人ChatGPT的开发者&#xff0c;OpenAI无疑是最受关注的人工智能公司之一。就是这家公司的联合创始人、CEO、有“ChatGPT之父”之称的阿尔特曼在“疯狂的5天”里&#xff0c;经历了被闪电免职、加入微软、最终又官复原…

影响嵌入式项目成功的一些要素

选择了嵌入式开发这个技术领域&#xff0c;就相当于选择了一条充满挑战的技术开发道路。 对于工程师而言&#xff0c;项目的成功和失败对他们十分重要。因为一行行代码他们不知道熬了多少个通宵&#xff0c;脑细胞死了多少而写出来的。 如果项目失败了&#xff0c;就意味着辛辛…

移动开发新的风口?Harmony4.0鸿蒙应用开发基础+实践案例

前段时间鸿蒙4.0引发了很多讨论&#xff0c;不少业内人士认为&#xff0c;鸿蒙将与iOS、安卓鼎足而三了。 事实上&#xff0c;从如今手机操作系统竞赛中不难看出&#xff0c;安卓与iOS的形态、功能逐渐趋同化&#xff0c;两大系统互相取长补短&#xff0c;综合性能等差距越来越…

【Element】el-select下拉框实现选中图标并回显图标

一、背景 需求&#xff1a;在下拉框中选择图标&#xff0c;并同时显示图标和文字&#xff0c;以便用户可以直观地选择所需的图标。 二、功能实现 <template><div><el-table ref"table" :data"featureCustom2List" height"200"…

分享71个Java源码总有一个是你想要的

分享71个Java源码总有一个是你想要的 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1frK-W3GT8WrydSlQ-E3o6A?pwd6666 提取码&#xff1a;6666 UI代码 def __init__(self):import …

Text2SQL学习整理(五)将Text-to-SQL任务与基本语言模型结合

导语 上篇博客&#xff1a;Text2SQL学习整理&#xff08;四&#xff09;将预训练语言模型引入WikiSQL任务简要介绍了两个借助预训练语言模型BERT来解决WIkiSQL数据集挑战的方法&#xff1a;SQLOVA和X-SQL模型。其中&#xff0c;借助预训练语言模型的强大表示能力&#xff0c;S…

【Gitlab】CICD流水线自动化部署教程

第一步&#xff0c;准备 GitLab 仓库 这个不用多说&#xff0c;得先保证你的项目已经托管在一个 GitLab 仓库中。 第二步&#xff0c;定义 .gitlab-ci.yml 文件 在你的项目根目录中创建一个 .gitlab-ci.yml 文件。这个文件将定义所有 CI/CD 的工作流程&#xff0c;包括构建、测…

C++中的内存锁定

内存锁定(memory locking)是确保进程保留在主内存中并且免于分页的一种方法。在实时环境中&#xff0c;系统必须能够保证将进程锁定在内存中&#xff0c;以减少数据访问、指令获取、进程之间的缓冲区传递等的延迟。锁定内存中进程的地址空间有助于确保应用程序的响应时间满足实…