歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> top命令引起系統負載升高

top命令引起系統負載升高

日期:2017/2/28 14:25:25   编辑:Linux教程

Linux系統環境:CentOS 6.5 x86_64

一、問題表現

系統負載升高,某一個核的cpu資源被top進程耗盡,如下圖所示:

二、分析過程

1.通過strace命令打印top進程信息,出現大量重復的系統調用,如下:

查看top進程的fd信息如下:

通過以上信息推斷,top進程的輸入輸出異常,觸發select返回文件描述符,但是文件描述符未處理或處理不當造成select無限觸發,陷入死循環,占用一個核的cpu資源。

2.下載procps-3.2.8查看top源碼,在第3398行找到了相關調用。如代碼所示標准輸入被放到了select調用裡,因為標准輸入錯誤導致觸發select返回fd,無tv時長的等待。

3.

long file_flags;
int rc;
char c;
fd_set fs;
FD_ZERO(&fs);
FD_SET(STDIN_FILENO, &fs);
file_flags = fcntl(STDIN_FILENO, F_GETFL);
if(file_flags==-1) file_flags=0;
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK|file_flags);

// check 1st, in case tv zeroed (by sig handler) before it got set
rc = chin(0, &c, 1);
if (rc <= 0) {
// EOF is pretty much a "can't happen" except for a kernel bug.
// We should quickly die via SIGHUP, and thus not spin here.
// if (rc == 0) end_pgm(0); /* EOF from terminal */
fcntl(STDIN_FILENO, F_SETFL, file_flags);
select(1, &fs, NULL, NULL, &tv);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK|file_flags);
}
if (chin(0, &c, 1) > 0) {
fcntl(STDIN_FILENO, F_SETFL, file_flags);
do_key((unsigned)c);
} else {
fcntl(STDIN_FILENO, F_SETFL, file_flags);
}

4.標准輸入的處理代碼如下:

static int chin (int ech, char *buf, unsigned cnt)
{
int rc;

fflush(stdout);
if (!ech)
rc = read(STDIN_FILENO, buf, cnt);
else {
tcsetattr(STDIN_FILENO, TCSAFLUSH, &Savedtty);
rc = read(STDIN_FILENO, buf, cnt);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &Rawtty);
}
// may be the beginning of a lengthy escape sequence
tcflush(STDIN_FILENO, TCIFLUSH);
return rc; // note: we do NOT produce a vaid 'string'
}

5.rc為read返回值,分三類返回正的字節數、0(表示到達文件末尾)、返回負值-1(表示出錯)。源碼中 rc==0的情況被注掉了(如下圖)造成標准輸入fd未處理,select的超時未生效。

6.top在運行時出現標准輸入異常這種情況一般是很難發生的,通過ps -fe 打印出了top的進程關系如下:

sudo 進程的pid變成1了,通過 ssh -t ‘strace -o sudo.strace sudo -i’ 抓取信息如下:

在終端異常關閉(斷網)後,並未退出,將父進程設成1繼續運行。

7.經測試在ssh -t ‘sudo -i’ 這種方式登陸,sudo的父進程是sshd,當終端異常關閉時sudo會將自己的父進程改為1繼續運行。正常登陸後在運行sudo的,sudo的父進程一般為bash(也可能是其他shell),不會出現類似情況。

三、總結

因線上環境很多操作需要切換到root,為了方便在ssh登陸的時候加上了 -t ‘sudo -i’ 的參數,從而導致了悲劇的發生。捷徑隨好但要小心陷阱,一不小心就可能釀成大錯。

注:

1.setsid top 或者其他守護進程調用top,當終端異常退出引起標准輸入錯誤時都會造成top異常。

2.Ubuntu系統不存在此問題,debian修復了此問題。

nicai@bugaosuni:~/procps-3.2.8/debian/patches$ cat top_stdin_eof.patch
Description: Check for stdin eof if term
Author: Samuel Thibault <[email protected]>
Bug-Debian: http://bugs.debian.org/458986
Reviewed-by: Craig Small <[email protected]>
Index: b/top.c
===================================================================
--- a/top.c 2009-11-24 21:00:34.000000000 +1100
+++ b/top.c 2009-11-24 21:00:35.000000000 +1100
@@ -3408,9 +3408,8 @@
// check 1st, in case tv zeroed (by sig handler) before it got set
rc = chin(0, &c, 1);
if (rc <= 0) {
- // EOF is pretty much a "can't happen" except for a kernel bug.
- // We should quickly die via SIGHUP, and thus not spin here.
- // if (rc == 0) end_pgm(0); /* EOF from terminal */
+ if (rc == 0) end_pgm(0); /* EOF from terminal, may happen if top
+ * erroneously gets detached from it. */
fcntl(STDIN_FILENO, F_SETFL, file_flags);
select(1, &fs, NULL, NULL, &tv);
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK|file_flags);
nicai@bugaosuni:~/procps-3.2.8/debian/patches$

實用的top命令 http://www.linuxidc.com/Linux/2014-11/109769.htm

為什麼 Linux 的 htop 命令完勝 top 命令 http://www.linuxidc.com/Linux/2014-06/102626.htm

Ubuntu下最強大的進程監視器htop使用 http://www.linuxidc.com/Linux/2013-05/85030.htm

CentOS 6.5中安裝htop進程管理監控工具 http://www.linuxidc.com/Linux/2014-03/97775.htm

Copyright © Linux教程網 All Rights Reserved