Linux 多线程调试(内存占用、死循环、CPU占用率高……)

文章出处:http://www.cnblogs.com/cy568searchx/archive/2013/10/28/3391790.html

你的软件在某个时刻停止服务,CPU占用达到100%+,这种问题一个可能的原因是产生了死循环,假设程序某处存在潜在的死循环,并在某种条件下会引发,本文以一个示例来定位出现死循环的位置。
当程序某处存在死循环,通常定位问题及缩小范围的方法是,在可疑的代码处加log,或者注释掉可疑代码,这对于容易重现问题的程序来说还好,但对于“偶尔”才会产生问题程序却很难调试,因为我们很难重现程序故障。本文所述的调试过程正是在这种情况下,假设问题已经出现,我们要求环境保护现场,即出问题的程序还在运行中。

1.我们首先要知道是哪个线程出了问题:
首先查一下出问题进程的pid,例如

[email protected]:~/MASS4/src/icdn/src$ ps -ef | grep icdn 

ovtsvn   11065     1 50 11:57 ?        00:00:07 ./icdn 

ovtsvn   11076 10971  0 11:57 pts/2    00:00:00 grep

[email protected]:~/MASS4/src/icdn/src$

[email protected]:~/MASS4/src/icdn/src$

然后top命令查看线程信息:
top -H -p 11065

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                 

11073 ovtsvn    25   0  325m 3980 2236 R  100  0.4   1:40.84 icdn                                                                    

11065 ovtsvn    18   0  325m 3980 2236 S    0  0.4   0:00.01 icdn                                                                    

11066 ovtsvn    18   0  325m 3980 2236 S    0  0.4   0:00.00 icdn                                                                    

11067 ovtsvn    15   0  325m 3980 2236 S    0  0.4   0:00.00 icdn                                                                    

11068 ovtsvn    15   0  325m 3980 2236 S    0  0.4   0:00.00 icdn                                                                    

11069 ovtsvn 180 325m 39802236 S 00.40:00.00 icdn 

11070 ovtsvn 180 325m 39802236 S 00.40:00.00 icdn 

11071 ovtsvn 220 325m 39802236 S 00.40:00.00 icdn 

11072 ovtsvn 150 325m 39802236 R 00.40:00.00 icdn

从上面可以看出,出问题线程PID为11073

2.接下来,我们用gdb来attach目标进程
执行: gdb icdn 11065
在gdb中,列出线程状态:

(gdb) info threads 

9 Thread 47056948181264 (LWP 11066)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 

8 Thread 47056956573968 (LWP 11067)  0x00002acc4a406fc2 in select () from /lib/libc.so.6 

7 Thread 47056964966672 (LWP 11068)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 

6 Thread 47056973359376 (LWP 11069)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 

5 Thread 47056981752080 (LWP 11070)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 

4 Thread 47056990144784 (LWP 11071)  0x00002acc4a40e63c in recvfrom () from /lib/libc.so.6 

3 Thread 47057194060048 (LWP 11072)  0x00002acc4a406fc2 in select () from /lib/libc.so.6 

2 Thread 47057226893584 (LWP 11073)  CSendFile::SendFile (this=0x2acc5d4aff40, [email protected])     at ../src/csendfile.cpp:101 

1 Thread 47056939784832 (LWP 11065)  0x00002acc4a3dec91 in nanosleep () from /lib/libc.so.6 (gdb)

gdb已经列出了各线程正在执行的函数,我们需要更多信息,记住11073对应的行首标号,这是gdb为线程分配的id,这里为2,然后执行切换:

(gdb) thread 2 

[Switching to thread 2 (Thread 47057226893584 (LWP 11073))]#0  CSendFile::SendFile (this=0x2acc5d4aff40, [email protected])     at ../src/csendfile.cpp:101 101             while(1) 

(gdb)

bt一下:

(gdb) bt 

#0  CSendFile::SendFile (this=0x2acc5d4aff40, [email protected]) at ../src/csendfile.cpp:101 

#1  0x000000000040592e in CIcdn::TaskThread (pParam=0x7fff617eafe0) at ../src/cicdn.cpp:128 

#2  0x00002acc4a90b73a in start_thread () from /lib/libpthread.so.0 

#3  0x00002acc4a40d6dd in clone () from /lib/libc.so.6 

#4  0x0000000000000000 in ?? ()

来看一下101行的代码:

(gdb) l 

96      } 

97 

98      int CSendFile::SendFile(const string& pathname) 

99      {

100             int n;

101             while(1)

102             {

103                     n++;

104             }

105             //read file and send

现在我们定位到了出问题的代码位置,这里的循环只用来演示的。 
最后别忘了detach()

调试完指定进程后,可以运行detach命令来让GDB释放该进程,该进程得以继续运行。当回车时,detach不会重复。当执行完detach后,进程和GDB不再相关,GDB可以attach其他进程。

时间: 2024-08-24 21:32:54

Linux 多线程调试(内存占用、死循环、CPU占用率高……)的相关文章

C++ 多线程编程解决CPU占用率高问题

在用C++进行多线程编程的时候,时常需要写一些类似于死循环的结构来执行代码,这些死循环如果没有经过处理一直开着,那么CPU的占用率就会居高不下的做着很多无用的操做.为解决这个问题我们可以通过在各线程中的适当位置添加Sleep函数来休眠该线程,使其少做这些无用的操作.经过这个处理,正常能压缩掉一半以上的CPU占用.C++ 多线程编程解决CPU占用率高问题

Linux下java进程CPU占用率高分析方法

Linux下java进程CPU占用率高分析方法 在工作当中,肯定会遇到由代码所导致的高CPU耗用以及内存溢出的情况.这种情况发生时,我们怎么去找出原因并解决. 一般解决方法是通过top命令找出消耗资源高的线程id,利用strace命令查看该线程所有系统调用 1. 通过top命令找到可疑进程PID top - 09:37:18 up 70 days, 16:29, 2 users, load average: 1.13, 1.04, 0.97 Tasks: 105 total, 1 running

Linux下分析某个进程CPU占用率高的原因

  Linux下分析某个进程CPU占用率高的原因 通过top命令找出消耗资源高的线程id,利用strace命令查看该线程所有系统调用  1.top 查到占用cpu高的进程pid 2.查看该pid的线程:top -H -p 9532 3.查看这个线程所有系统调用:strace -p 10017 不停循环输出Connection timed out,让开发查看问题 原文地址:https://www.cnblogs.com/chenjw-note/p/8370679.html

一次服务器CPU占用率高的定位分析

背景 通过性能监控发现上线服务器cpu某核占用率已经达到了100%,而且是由我们的某个核心服务导致的.幸亏由于我们的服务进程由多个相同worker(线程)调度承担的,所以除了CPU占用率高之外,并没有对服务造成影响.随着上次我们找到那个吃IO的罪犯,这次我们要追捕的是潜伏在团体中的特务,更加惊险刺激哟! 系统环境 用top命令很容易定位到是谁占用CPU最高. 以我们的这个业务进程(imDevServer)举例,为什么说这货是个潜伏者呢?因为这是个多线程的进程,我们要知道实际上占用cpu的最小单位

Java CPU占用率高分析

首先,通过top命令找出CPU占用率高的进程: 然后,通过ps -mp 2066 -o THREAD,tid,time命令找出执行时间最长的线程的TID 将有问题的TID转为16进制格式: printf "%x\n" TID 最后,通过jstack 2066 | grep --color -E '2ab7|2ab8' -A 30命令打印线程的堆栈信息: 这些信息对于我这个运维来说,简直是天书,所以,我只需将它们发给开发即可.

刚装完Linux就CPU占用率高

top命令发现如下三个进程占据了前三的CPU使用率 wpa_supplicant NetworkManager rsyslogd google发现前两个进程与无线网络有关,我的电脑是笔记本,插的有线,无线被硬件禁止了,所以电脑一直在试图开启无线功能导致CPU占用率在空载的情况下达到80%的水平,后来在软件中也将无线给禁止了就好了.

while循环&CPU占用率高问题深入分析与解决方案

直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方.使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器).因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题.具体项目代码就不贴了,类似于下面这段代码. while(flag) { //your code; } 这里的flag可能是tru

maridb 10.3 主从复制,待机情况下从库 cpu 占用率高的处理方法

发现两台从库,一直都在CPU 占用率 60% 90% 中浮动, 但是写库却很正常.搜了一大把没找到答案,把参数测试了一下得出以下结论 slave  my.cnf 添加如下参数 #只读模式 read_only = 1 #当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性. relay_log_recovery = 1 # mariadb启动报错,不支持此

linux CPU占用率高(转)

来自:http://www.cnitblog.com/houcy/archive/2012/11/28/86801.html 1.用top命令查看哪个进程占用CPU高 gateway网关进程14094占用CPU高达891%,这个数值是进程内各个线程占用CPU的累加值. PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND     14094 root      15   0  315m  10m 7308 S 891

[Linux小技巧] 一行命令让CPU占用率达到100%

for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`; do dd if=/dev/zero of=/dev/null & done 说明: cat /proc/cpuinfo |grep "physical id" | wc -l 能够获得CPU的个数, 我们将其表示为N. seq 1 N 用来生成1到N之间的数字 for i in `seq 1 N`; 就是循环运行命令,从1到N