1. 死锁介绍

1.1 锁的简介

由于多线程的模式下,各个线程并发运行(注意“并发和“并行”的区别),为了保证各个线程对公共资源的访问时出现数据不一致性的问题,出现了锁的机制。

Linux系统编程中最常见的锁机制是通过互斥量(mutex)来实现的。任一时刻只有一个线程可以对互斥量mutex上锁(或说成持有该互斥量),在被持有期间,其它线程就无法对它进行上锁(这也是互斥量名字中“互斥”的由来),其它尝试加锁的线程都会休眠(注意休眠和挂起的区别)释放cpu资源,并被记录到此互斥量的等待队列中。持有的线程释放互斥量后,内核会根据调度机制从等待队列中选择一个线程使其持有互斥量,队列中的其它线程将会继续等待。

1.2 死锁的常见形式

网上关于死锁的资料有很多,比如死锁形成的四要素等等。我这里只按我的理解以白话的形式进行说明。死锁的两种常见形式为 "AA" 和 "ABAB"

(1)AA:重复上锁

发生在同一个线程中,加锁后未解锁就再次加锁,最常发生错误的情况就是程序异常退出循环前没有释放锁,导致再次上锁后发生错误,伪代码模型如下:

(2)ABBA:多个线程持有彼此在等待的锁

线程线程1持有锁A,线程2持有锁B,同时线程1等待锁B,线程2等待锁A,这种情况下就会一直死等下去。

2. GDB调试死锁的实例

2.1 写一个死锁程序

mutex.c,代码如下:

   #include<unistd.h>#include<pthread.h>pthread_mutex_t mutex_1 = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t mutex_2 = PTHREAD_MUTEX_INITIALIZER;void *pthread_test_1(void *arg){pthread_mutex_lock(&mutex_1);sleep(1);   //休眠以保证pthread_test_2线程运行至持有mutex_2pthread_mutex_lock(&mutex_2);pthread_mutex_unlock(&mutex_1);pthread_mutex_unlock(&mutex_2);}void *pthread_test_2(void *arg){pthread_mutex_lock(&mutex_2);sleep(1);    //休眠以保证pthread_test_1线程运行至持有mutex_1pthread_mutex_lock(&mutex_1);pthread_mutex_unlock(&mutex_2);pthread_mutex_unlock(&mutex_1);}int main(void){pthread_t tid1, tid2;pthread_create(&tid1, NULL, pthread_test_1, NULL);pthread_create(&tid2, NULL, pthread_test_2, NULL);pthread_join(&tid1, NULL);pthread_join(&tid2, NULL);return 0;}

2.2 GDB调试过程

gcc 编译:gcc mutex.c -o ppt,我这里给可执行程序随便起了一个名字叫“ppt”

(1)运行死锁程序

事先运行可执行程序./ppt,然后再启动GDB进行调试(因为正常情况很可能就是这样:事先已经运行了程序,发现它可能产生死锁,所以我们用GDB对它进行调试)。

(2)pidof命令获取进程号

(3)启用GDB,然后attach [PID]调试已经在运行的进程

注:启用gdb 然后attach [PID]发现Operation not permitted,提示,我们可以try as root。

(4)查看线程的堆栈信息

thread apply all bt:查看所有线程的堆栈信息

当发现有多个线程停留在 "__lll_lock_wait" 上时,很可能说明发生了死锁,或者其它问题比如持有锁的线程无法退出,导致其他线程都阻塞在了加锁上。

从上图可以看出pthread_test_2这个线程在等待给mutex_1上锁,pthread_test_1这个线程在等待给mutex_2上锁,还不能就此判断出发生了死锁。需要在进一步查看mutex_1和mutex_2的信息。

(5)查看锁的信息

1)如果知道互斥量的名字,可以直接运行 "print mutex_name"命令来查看。

2)如果不知道互斥量的名字,可以通过 "获取互斥量地址处的数据方式" 来查看

print *(pthread_mutex *)(address):就是从address所标识的地址处取出pthread_mutex类型的数据。

由上图可以看出,mutex_1被ID为9641的线程持有,而9641为pthread_test_1,mutex_2被ID为9642的线程持有,而9642为phtread_test_2。

综上:pthread_test_1持有mutex_1,等待mutex_2,pthread_test_2持有mutex_2,等待mutex_1,得出结论发生了死锁。

Linux GDB调试死锁问题相关推荐

  1. linux子系统gdp调试,Linux GDB调试 详述

    今天来分享下gdb的简单调试,我这里写了个例子 三个.c文件 func1.c func2.c main.c 首先生成可调试的执行文件 gcc -g func1.c func2.c main.c -o ...

  2. Linux GDB分析死锁

    目录 示例代码 分析 结论 示例代码 // DeadLock.cpp : 定义控制台应用程序的入口点. //#include <iostream> #include <stdlib. ...

  3. Linux gdb调试器

    gdb的启动 --gdb 程序名 [corefile] --corefile是可选的,但能增强gdb的调试能力 --强调:启动gdb必须在编译命里加上"-g"参数,"-g ...

  4. Linux GDB调试

    Linux 段错误调试 core 文件调试 编译时 加上 -g 使编译出的文件带 调试信息 gcc -g main.c -o main 使编译出的可执行文件带调试信息gdb main //对 main ...

  5. [Linux]gdb调试多进程多线程例程

    gdb相信学linux的同学已经比较熟悉了吧,它是linux下代码调试工具.我们在写c语言,c++的代码时经常会用到,它有一些常用的调试命令: run(r):运行程序,如果有断点在下一个断点处停止 s ...

  6. Linux gdb调试(4):多进程与多线程调试

    一,gdb的基础知识 1>介绍: gdb是Linux环境下的代码调试工具. 2>使用:需要在源代码生成的时候加上 -g 选项. 3>开始使用: gdb binFile 4>退出 ...

  7. Linux GDB调试完全教程

    转自 http://blog.csdn.net/gatieme 本文将主要介绍linux下的强大调试工具是怎么完成这些工作的. 之所以要调试程序,是因为程序的运行结果和预期结果不一致,或者程序出现运行 ...

  8. linux gdb检查函数栈,Linux - gdb调试

    调试 调试工具:gdb的使用 编译后版本 编译后的成果分为两个版本: debug版本:调试版本 -->程序员使用 release版本:最终发行版本 -->最终用户使用 gcc默认生成的是r ...

  9. Linux——gdb调试时多进程切换方法(attach/follow-fork-mode)

    对于程序中创建子进程的情况,进行gdb调试时会默认选择父进程进行调试,假如需要对子进程进行调试就需要使用特殊方法. 共有两种方法可供选择: 目录 一.attach子进程PID ①.运行进程 ②获取进程 ...

最新文章

  1. sql中小数位四舍五入控制
  2. 高可用keepalived实例
  3. 框架:DAO,Service,Controller,View层之间的逻辑关系
  4. 他被女朋友拉黑后,写了个“舔狗”必备神器
  5. Apache Ignite的Node.js客户端使用入门
  6. 单片机设置12分频c语言,AT89C51单片机,如何实现延迟一秒
  7. 15款Cocos2d-x游戏源码
  8. merge卷积和bn层的原理
  9. Openwrt 路由器挂载摄像头教程
  10. 弹出层之3:JQuery.tipswindow
  11. cocos2dx lua代码和图片资源加密和解密
  12. 很值得看看的中文翻译The Django Book
  13. 嵌入式开发自救指南(嵌入式怎么高薪基本思路)
  14. C语言结构体,共用体所占字节数计算
  15. 学习MIT 6.824 部分笔记
  16. 华硕发布全球首款8G内存手机ZenFone VR
  17. 苹果cms(mac cms)安装和避雷
  18. css33d图片轮播_通过html+css3实现图片轮播切换
  19. HTML+CSS画圣诞树
  20. 1、关于百兆口、千兆口、万兆口端口和网线的小常识

热门文章

  1. 满是忧愁却又心满意足
  2. 银行数字化转型导师坚鹏:数字化时代普惠金融模式和产品创新
  3. Clickhouse Explain
  4. 小程序内使用setInterval()循环执行,退出页面时停止
  5. Python编程:聊天群的屏蔽脏话
  6. 魔兽中各族单位名称英文缩写
  7. c4d软件安装上打开不了_Homebrew :在 Mac 上无痛安装软件 | Linux 中国
  8. Jetson 系列——基于yolov5对火源或者烟雾的检测,使用tensorrt、c++和int8加速
  9. dataguard跨平台linux,Dataguard从库性能的监控
  10. 多线程并发-线程状态切换-后宫狗血剧情版,看完彻底掌握线程状态切换流程