strace命令,是Linux提供的跟踪系统调用的命令,需要sudo或root权限,可以查看进程(线程)使用的系统调用。

基本用法:sudo strace -p 进程号

如果一个线程递归获取同一个锁,或者多个线程以不同的顺序获取多个锁,那么就会导致至少有一个线程在持有锁的情况下再次等待在一个锁上(持有的锁和等待的锁可能相同或不同),导致死锁(deadlock)。

这时,至少有一个线程会等在futex()系统调用上,可以使用strace命令查看具体哪个线程等在哪个锁上。

看图中的例子,线程函数thread()连续两次调用pthread_mutex_lock()加锁g_mutex,导致递归死锁。

这时它等在futex系统调用上,等待的锁是g_mutex。

如果main函数里打开注释的pthread_join,那么是等不到子线程返回的。

假设程序的文件名是a.out,在死锁后:

1,首先使用ps -ef | grep a.out 查看所有的名字叫a.out的进程,如图。

进程号2992的就是a.out,随后的2609表示的是父进程,即启动它的shell进程的pid。

2,使用top -H -p 2992查看该进程下的所有线程,这里只有2个线程,其中与2992同号的是主线程。

top -H -p 进程号,可以查看所有的线程,其中%CPU显示该线程的CPU使用率,越活跃的线程这个值越大。

这里只是为了获取所有的线程号。

3,然后用sudo strace -p 线程号,去跟踪它的系统调用。

2992调用了nanosleep ()函数,纳秒休眠,与我们在函数里写的while (1) sleep(1);代码相符合。

2993则调用了futex()函数,且等待的锁的地址是0x557a41002040。

4,这时,可以在锁的初始化的地方,打印锁的地址,这里是main函数的第24行,打印的地址对应的锁为g_mutex。

然后我们可以查看代码里使用了g_mutex加锁的地方,可以确定是16、17行的两次加锁导致的。

这么几行代码,是写不出这问题的:(

只有代码复杂起来之后,在一定条件下概率触发的死锁,才是实际项目里的常见情况。

这时,strace命令直接确定死锁的线程和锁的地址的作用,才可以发挥出来。

只要在步骤4的调试信息中打印了可能导致死锁的锁地址,在问题再次出现时就可以用strace跟踪到目标锁的变量,进而查到错误代码的位置。

像上图那么一改,是不是BUG就不显眼了:( 捂脸

main函数第43行的continue会跳过45行的解锁,导致第40行递归死锁,和thread函数的第19行死锁。

它是个概率问题,因为100是1000的因子,只有thread线程把g_count++到正好是100的倍数,然后在它下一次++之前main线程获取了锁,执行到第42行的if条件,才会出现continue越过45行的解锁,然后死锁。

下图的ctrl+c卡断的地方,就是出现了死锁的例子。

PS:如果把第42行的100改成500,降低if成立的概率,那么死锁的概率会降低。

如果在thread函数的while循环里加usleep睡眠,那么相当于提高了main函数获得锁的成功率,死锁的概率会提高。

这两个办法可以在调试时采用。

用户态程序,其实不怎么怕死锁,而是怕该锁的时候没锁,把malloc申请的内存破坏了,导致下一次不知道哪里free或malloc的时候程序挂了。

这属于多线程+竞争条件+野指针,C语言里最无语的BUG之一。

另一个是内核的自旋锁死锁,只要锁住一块CPU,就会锁住所有CPU,然后printk()打印不了信息了。

举报/反馈

linux 跟踪命令执行过程,Linux的strace命令跟踪线程死锁相关推荐

  1. Linux命令执行过程中的配置文件信息

    命令执行过程 前面讲到过使用 alias 可以建立别名,比如创建了一个 ls 的别名,其实 ls 有少的指令,那么到底是哪一个会被选中执行呢?基本上,指令运行顺序可以这样看: 以相对.绝对路径执行命令 ...

  2. Linux 命令的执行过程/Shell提示符/alias命令

    在 Linux 系统中"一切皆文件",Linux 命令也不例外.那么,当编辑完成 Linux 命令并回车后,系统底层是怎么执行的? 1) 内核层 内核层是 UNIX/Linux 系 ...

  3. linux命令执行的通过程,Linux下shell命令执行过程简介

    浅析linux 下shell命令执行和守护进程 执行shell脚本有以下几种方式 1.相对路径方式,需先cd到脚本路径下 [root@banking tmp]# cd /tmp [root@banki ...

  4. linux每隔多久调度y,Linux 进程调度+Linux系统一般执行过程 笔记

    进程的调度时机与进程的切换 操作系统原理中介绍了大量进程调度算法,这些算法从实现的角度看仅仅是从运行队列中选择一个新进程,选择的过程中运用了不同的策略而已. 对于理解操作系统的工作机制,反而是进程的调 ...

  5. Linux 系统调用的执行过程

    什么是系统调用 系统调用 (在 Linux 中常称为 syscalls ) 是应用程序访问硬件设备之间的桥梁. 系统调用层为用户空间提供一种硬件的抽象接口,使得用户不用关注设备的具体信息,同时系统调用 ...

  6. linux进程上下文切换的具体过程,Linux实验三 结合中断上下文切换和进程上下文切换分析Linux内核一般执行过程...

    fork系统调?创建?进程,也就?个进程变成了两个进程,两个进程执?相同的代码,只是fork系统调?在?进程和?进程中的返回值不同. 打开linux-5.4.34/arch/x86/entry/sys ...

  7. 分析teamTNT团队Linux挖矿木马执行过程与防范

    分析teamTNT团队Linux挖矿木马执行过程与防范 公司需要扩展海外业务,需要有一台海外云服务器.当我们把应用部署上去时的第二天所有应用down掉了,然后发现ssh连接服务器特别慢.好不容易连接上 ...

  8. linux的保存命令执行结果,linux下把命令执行的结果输出

    我们知道在linux下当我们想把文字用命令输入到一个文本下时可以用echo命令 例:echo "nihao" > /z.txt 同样当我们想把命令执行的结果也输入到一个文本时 ...

  9. 初探 Go 的编译命令执行过程

    引言 Go 语言这两年在语言排行榜上的上升势头非常猛,Go 语言虽然是静态编译型语言,但是它却拥有脚本化的语法,支持多种编程范式(函数式和面向对象).Go 语言最最吸引人的地方可能是其原生支持并发编程 ...

最新文章

  1. java杂记-static
  2. python 配置文件对比_Python运维自动化之nginx配置文件对比操作示例
  3. Linux命令缩写来由
  4. 全球及中国垃圾发电行业运营管理及十四五投资价值评估报告2021-2027年
  5. QT mouseMoveEvent事件(qmainwindow内追踪鼠标事件事件)
  6. 计算机是怎样知道屏幕位置的,如何看自己的电脑显示器是多少寸
  7. uva10050-罢工
  8. React单页如何规划路由、设计Store、划分模块、按需加载
  9. “睡服”面试官系列第十一篇之module加载实现(建议收藏学习)
  10. linux san网络,rhel5 – 使用Linux时,为什么我的MPIO连接到SAN的上限为1 Gbps?
  11. Java ME SDK 3.0.5发布!
  12. GitHub 和GitLab的开发工具使用
  13. 20190930每日一句
  14. HDU 1556 Color the ball 线段树
  15. 玻利亚(Polya)的《怎样解题》
  16. 马赛克(蒙太奇)图片生成--Python实现
  17. 面试经验分享,论如何入职心仪的企业
  18. Android 7.0修改分辨率,三星S7升级Android7.0 可调节屏幕分辨率
  19. CentOS6启动和内核管理
  20. java暂挂状态,Guarded Suspension(保护性暂挂)模式

热门文章

  1. gdx 打包可执行 jar 不会包含源码 src 目录下的资源
  2. Fusion360学习记录:甜甜圈模具
  3. Httprequest 获取url 常用方法
  4. 五位数回文数c语言程序,五位数的回文数有多少个
  5. Notepad工具软件配置Mycat schme.xml文件
  6. 【Redis】Redis实现排行榜及相同积分按时间排序
  7. 使用bootstrap搭建后台管理系统页面《二》
  8. python数据透视_用pythonwin32com创建数据透视图
  9. lin通信ldf文件解析_LIN总线开发之LDF文件介绍
  10. 键盘和鼠标事件中按键的数字是多少呢?event.which