背景知识:

1.tty

终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。

tty指的是七个alt+crtl+F1~F7。tty1-tty6表示文字界面,可以用Ctrl+Alt+F1-F6切换,+F7就是切换回图形界面,tty7一般是表示图形界面。

2. pty(虚拟终端):
我们远程telnet,ssh,serial到主机时也需要一个终端交互么,这就是虚拟终端pty(pseudo-tty)
 
3. pts/ptmx(pts/ptmx结合使用,进而实现pty):
pts(pseudo-terminal slave)是pty的实现方法,与ptmx(pseudo-terminal master)配合使用实现pty。
man里面是这样说的:ptmx and pts - pseudo-terminal master and slave,pts是所谓的伪终端或虚拟终端,具体表现就是你打开一个终端,这个终端就叫pts/0,如果你再打开一个终端,这个新的终端就叫pts /1。
比如用who命令查询当前登录的用户,可以看到每个用户的TTY设备(简单来说就是用户输入命令还有显示信息的设备,比如终端)。

要确定当前的终端,可以敲入tty命令即可显示。

--------------------------------正文,我只是分割线---------------------------

下面描述故障现象:

首先实现一个telnet服务器端程序,监听某个端口,登录之后,执行某些命令,比如top命令,这个时候肯定先创建一个会话,
openpty(&masterfd,&slavefd,tty_name,NULL,NULL),再使用tcsetattr等来设pts的属性。 然后要vfork一下,将对应pts的slavefd传给对应的子进程。父进程当然还得对telnet的客户端回复一些可协商的项目,比如

TELOPT_ECHO,
TELOPT_NAWS,
TELOPT_LFLOW,
TELOPT_ECHO, 
ITELOPT_SGA

构建命令行参数:

new_argv[0] = "sh";
new_argv[1] = "-c";
new_argv[2] = cmd;
new_argv[3] = NULL;

然后调用execvp("/bin/sh", (char **)new_argv) 来执行这个命令。
子进程流程是:
 fd = open(ptyname, O_RDWR);

dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);

这样输入输出就通过这个pts设备来通信了。而子进程对标准输入,输出,和error的操作都将是操作对应的pts设备。

问题出现在什么地方:如果上面的创建子进程的命令是su,切换到root,然后再执行命令top命令,这时候的父子关系如下:

telnet_proc----su----bash---top

当直接关闭telnet界面的时候,按道理发信号给进程组,然后全部退出,

但实际情况是,top有一定的几率获取不到这个信号,不光是top,整个进程组都没有收到信号,那么top的fd就会变为如下:

top 19663 root 0u CHR 136,26 0t0 29 /dev/pts/26 (deleted)
top 19663 root 1u CHR 136,26 0t0 29 /dev/pts/26 (deleted)
top 19663 root 2u CHR 136,26 0t0 29 /dev/pts/26 (deleted)

[root@localhost ~]# rpm -qf /usr/bin/top
procps-3.2.8-21.el6.x86_64

而top这个版本的代码中,是通过select超时来控制的,并且,没有对select的返回值做判断。

原本默认3秒钟一次的top,变成了1秒钟执行3次,(此时select操作而定fd1,是指向/dev/pts/26的,而这个设备,已经被masterfd删除了)

11:24:30 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:30 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:30 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:31 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999990})
11:24:31 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:31 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:32 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:32 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:32 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:33 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:33 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:33 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:33 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:34 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})
11:24:34 select(1, [0], NULL, NULL, {3, 0}) = 1 (in [0], left {2, 999998})

其实这个是在系统负荷大的时候的结果,系统系统负荷小,就是遍历的proc下的pid少的话,top在1秒钟之内,能执行很多次遍历,而这种遍历,带来的结果是top占用的那个核,cpu接近了100%。
当然还有些原因,是因为top继承了实时进程的属性,导致别人也不好抢它cpu。否则cpu会稍微低一些,但也不会低到哪去。

[root@localhost ~]# chrt -p 19663 
pid 19663 's current scheduling policy: SCHED_FIFO
pid 19663 's current scheduling priority: 76


接下来,回到问题的本质,为什么这种情况下没有接收到退出信号呢?

信号处理引发的cpu高的更多相关文章

  1. C#正则表达式引发的CPU跑高问题以及解决方法

    3月23日(周日)下午16:30左右,博客园主站负载均衡中的2台Web服务器CPU玩起了爬楼梯的游戏(见上图),一直爬到了接近100%.发现这个状况后,我们立即将这2台阿里云临时磁盘云服务器从负载均衡 ...

  2. 云计算之路-阿里云上:启用Windows虚拟内存引发的CPU 100%故障

    今天上午11:35~11:40左右,由于负载均衡中的两台云服务器CPU占用突然飚至100%,造成网站5分钟左右不能正常访问,请大家带来了麻烦,请谅解! (上图中红色曲线表示CPU占用) 经过分析,我们 ...

  3. Expert 诊断优化系列------------------你的CPU高么?

    现在很多用户被数据库的慢的问题所困扰,又苦于花钱请一个专业的DBA成本太高.软件维护人员对数据库的了解又不是那么深入,所以导致问题迟迟不能解决,或只能暂时解决不能得到根治.开发人员解决数据问题基本又是 ...

  4. 关于csrss.exe和winlogon.exe进程多、占用CPU高的解决办法,有人在暴力破解

    关于csrss.exe和winlogon.exe进程多.占用CPU高的解决办法 最近VPS的CPU一直处在100%左右,后台管理上去经常打不开,后来发现上远程都要好半天才反映过来,看到任务管理器有多个 ...

  5. linux c++应用程序内存高或者占用CPU高的解决方案_20161213

    对于绝大多数实时程序来说,实时处理相关程序中的循环问题所带来的对机器的损耗和自身的处理速度的平衡,以及与其他程序的交互以及对其他功能的影响难免会成为程序设计中最大的障碍同时也是最大的突破点. 在所有这 ...

  6. TortoiseSVN status cache占用CPU高

    进程占用CPU高 每次从SVN上更新资源时,电脑都会卡死,直到资源更新完.当要Commit资源时,SVN也会卡死资源管理器,如下图所示: 解决占用CPU高的问题 1.禁用图标缓存 2.排除路径和包含路 ...

  7. 定位CPU高的方法

    CPU占用高,最常见的原因是死循环或者类死循环的操作,如果要逐一排查代码,费时费力,可以先用工具 工具1.windbg,windows出品的牛刀一枚以管理员运行windbg,File->Atta ...

  8. 关于csrss.exe和winlogon.exe进程多、占用CPU高的解决办法

    原地址 http://blog.sina.com.cn/s/blog_912e77480101nuif.html   最近VPS的CPU一直处在100%左右,后台管理上去经常打不开,后来发现上远程都要 ...

  9. CPU高问题排查

    双11大战开始了,这几天公司系统压测,CPU各种报警,于是找了篇关于CPU高问题排查的文章. 一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环. (友情提示:本博文章欢迎 ...

随机推荐

  1. Neo4j学习笔记(2)——数据索引

    和关系数据库一样,Neo4j同样可以创建索引来加快查找速度. 在关系数据库中创建索引需要索引字段和指向记录的指针,通过索引可以快速查找到表中的行. 在Neo4j中,其索引是通过属性来创建,便于快速查找 ...

  2. TurnipBit开发板DIY呼吸的吃豆人教程实例

    转载请以链接形式注明文章来源(MicroPythonQQ技术交流群:157816561,公众号:MicroPython玩家汇) 0x00前言 吃豆人是耳熟能详的可爱形象,如今我们的TurnipBit也 ...

  3. Python爬虫知识点一

    一.入门知识: 1.1.HTTP简介HTTP = HyperText Transfer ProtocolURI = Uniform Resource IdentifierURL = Uniform R ...

  4. System.Windows.Forms.PropertyGrid的使用

    PropertyGrid 控件简介 .NET 框架 PropertyGrid 控件是 Visual Studio .NET 属性浏览器的核心.PropertyGrid 控件显示对象或类型的属性,并主要 ...

  5. PHP curl请求https遇到的坑

    PHP里curl对https的证书配置默认是服务器端要求验证的,如果服务器端没有配置证书验证,则无法请求https路径.如果为了简便使用不需要配置https证书的话,配置curl时将以下两项设置为fa ...

  6. Java学习笔记27(集合框架一:ArrayList回顾、Collection接口方法)

    集合:集合是java中提供的一种容器,可以用来存储多个数据 集合和数组的区别: 1.数组的长度是固定的,集合的长度是可变的 2.集合中存储的元素必须是引用类型数据 对ArrayList集合的回顾 示例 ...

  7. 【ASP.NET Core】在Win 10 的 Linux 子系统中安装 .NET Core

    在上一篇文章中,老周扯了一下在 Windows 10 中开启 Linux 子系统,并且进行了一些简单的设置.本篇咱们就往上面安装 .net core . 老周假设你从来没有用过 Linux,所以,接着 ...

  8. deeplearning.ai 人工智能行业大师访谈 Andrej Karpathy 听课笔记

    1. 本科的时候在多伦多大学上Geoffrey Hinton的课,在MNIST数字数据集上训练受限玻尔兹曼机,觉得很有趣.后来在UBC读硕士,上了另一门机器学习的课,那是他第一次深入了解神经网络的相关 ...

  9. 【经验分享】安装VirtualBox的时候遇到的问题

    错误代码: Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works. ...

  10. MATLAB命令大全+注释小结

    一.常用对象操作:除了一般windows窗口的常用功能键外.1.!dir 可以查看当前工作目录的文件.   !dir& 可以在dos状态下查看.2.who  可以查看当前工作空间变量名,    ...