先让我们来看看进程的虚拟地址中的0~3g用户空间的存储:




解决vmmem进程占用CPU资源的方法_数据


正文即代码段,初始化的数据段,未初始化的数据即bss段。bss段和初始化的数据段加在一起就是数据段。BSS段通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。特点是可读写的,在程序执行之前BSS段会自动清0。对bss不熟悉的同学可参考:BSS段_百度百科

然后再往上就是堆和栈了。再往上就是进程的命令行参数和环境变量了。开启一个终端,输入 env ,即可查看当前进程的环境变量。比如当前进程的使用者,进程的path环境变量等于多少,当前进程的pwd,即工作目录是在哪里等。还有home 目录, cd ~即可直接进入到home目录下,因为进程记录了波浪线就等于home目录。 环境变量就是以键值对的形式存储在3g以下,栈以上的内存空间内。

一个小的理解信息:在栈上定义一个10个字节的数组,然后你写入了100字节,没报什么错误,然后写1000个字节,就报内存错误,系统崩溃之类的信息。 因为栈上面一部分还是属于用户空间,所以大一点没多大事,可是再往上就是内核空间,用户不能进行访问和读写。所以报错。

下面就是一个基本的内存布局:


解决vmmem进程占用CPU资源的方法_vmware-vmx.exe无法结束进程_02


最后来一张《深入理解计算机系统》图:这个相比之下就比较权威。有毒,下面这张图片怎么都放不正。


解决vmmem进程占用CPU资源的方法_解决vmmem进程占用CPU资源的方法_03


注意:内核虚拟内存里面也是有代码、数据、堆、栈的啊! 注意内核空间中分各进程不一样和各进程一样的空间!

只是这里没有视频中提到的栈之上,内核之下的命令行参数和环境变量。

然后简单看下cpu的结构:


解决vmmem进程占用CPU资源的方法_读取当前linux进程内存_04


cpu主要由运算器,寄存器,控制器,译码器组成。

寄存器在这里扮演着很重要的角色。

比如上面a.out, b.out两个进程,里面的代码段其实都是操作寄存器里面的东西。写过汇编的基本都有些了解吧。 当a.out执行到一半,然后切换到b.out执行,那么寄存器的数据需要保存下来。cpu的寄存器的数据就叫处理器现场。那么这些数据保存到哪里呢?答案是:进程的虚拟地址中的内核空间里的内核栈中。 我们还记得pcb中保存着进程的运行位置等信息。所以,当再次切换回a.out进程执行的时候,就是通过pcb找到内核栈,然后通过内核栈恢复处理器现场,然后读取上次运行到的位置继续运行代码段。

而这些进程的切换都是由操作系统来完成,也就是操作系统完成进程调度。

进程调度最小单位是时间片,以前的cpu时间片是10ms,就是说一个进程运行10ms就停止了,换下一个时间片在这个cpu上运行(可能还会调度到这个进程)

额,其实我之前学习的都是线程的调度的,不知道为啥这个视频总是以进程作为cpu调度。

然后这里讲进程的状态分为4种:运行,就绪,睡眠,停止


解决vmmem进程占用CPU资源的方法_数据_05


运行和就绪可以互相转换,运行可以变为睡眠。睡眠、运行、就绪都可以直接变为停止。kill就是直接停止进程了。要到运行状态,必须先到就绪状态。(感觉这部分知识都比较基础)

ps aux看到 stat为s的就是睡眠,比如调用sleep函数,阻塞等。

不过这视频并没有讲具体的进程状态,有点伤,只能充当了解吧。

现在来补充一下关于linux的进程状态:

我们通常都知道使用ps aux指令去查看进程的信息:如下图


解决vmmem进程占用CPU资源的方法_vmware-vmx.exe无法结束进程_06


然后里面的STAT就是显示的进程的状态信息。

主要的状态有:

  1. R(running /runnable) 该进程正在运行中;

2. S(sleep) 该进程目前正在睡眠状态(idle),但可以被唤醒(signal);

3. D: 不可被唤醒的睡眠状态(也叫不可中断状态),通常这个进程可能在等待I/O的情况(比如 打印)

4. T :停止状态(stop),可能是在工作控制(后台暂停)或出错状态

5. Z : 僵尸状态(Zombie),进程已经终止却无法被删除至内存外。

然后我们来看看R状态:可运行状态指的是就绪和运行两个状态(runnable or runnable)的,也就是正在使用cpu和等待cpu的进程,反正都在参与着时间片的调度。学操作系统的时候我们对就绪和运行这两个概念比较熟悉,所以这样说可能比较容易理解。

然后看看D状态: 不可被唤醒的睡眠状态,也叫不可中断状态。不可中断状态指的是进程正处于内核态关键流程中的进程,并且这些进程是不可打断的。比如向一个进程向磁盘读写数据时,为了保证数据的一致性,它是不可以被其它进程或者中断打断的。如果此时的进程被打断,就会出现进程数据和磁盘数据不一致的问题。所以,不可中断状态实际上是系统对进程和硬件设备的一种保护机制。D状态即是不可中断状态,即uninterruptibe sleep或disk sleep。如果要改变这种状态,需要满足这个进程的io事件,或者重启电脑

然后来看看Z状态,也就是常说的僵尸状态。通常,造成僵尸进程的原因是因为该进程应该已经执行完毕,或者是因故要终止了,但是该进程的父进程却无法完整将该进程结束掉,而造成那个进程一直存在内存当中。如果某个进程的cmd后面还接上 <defunct>时,就代表该进程是僵尸进程。

当系统不稳定的时候就容易造成所谓的僵尸进程,可能是因为程序写得不好,或者是用户的操作习惯不良等所造成的。通常我们都是跟踪这个僵尸进程的父进程,然后进行相应优化和改善。不要只是直接杀掉父进程,可能会一直产生僵尸进程

事实上,通常僵尸进程都已经无法看管,而直接交给init这个程序来负责,而init是系统执行的第一个程序,它是所有进程的父进程。我们无法杀掉这个进程,如果我们它不自己慢慢删除,我们有搞定不了,就只能重启系统了。(我的理解就是,父进程里负责创建子进程和回收子进程,子进程结束了,但是没回收,也就是PCB,虚拟内存之类的东西一直占据着内存,就会导致系统的内存泄漏。)

然后就是状态后面的一些标识了:

< 高优先级

N 低优先级

L 有些页被锁进内存

s 包含子进程

+ 位于后台的进程组;

l 多线程,克隆线程

感觉进程管理这方面,鸟叔的linux私房菜讲得不错,推荐一下。