公众号「码农小奎」操作系统—进程篇
所谓进程,第一能想到的就是应用程序。打开浏览器,这是一个进程,挂上QQ,这也是一个进程。很明显,这是能真实感受到的。
除了这些能看到的以外,在数据层面上,进程到底是什么形态?为什么需要进程?进程是怎样运行于计算机之上的?
在windows中,你肯定用过任务管理器,那里展现的就是一个个进程。
在Linux终端下输入ps命令也可以查看进程,这里所显示的都是进程的具体数据,例如进程ID、进程名、占用CPU百分比、进程创建和运行时间等。
![Linux下ps命令查看进程](https://i-blog.csdnimg.cn/blog_migrate/80bf9cd2918735ab65224ee8b9b49f24.jpeg)
依靠这种数据结构综合起来就是一个进程了。
看到这,是不是感觉进程很简单,其实也确实如此,在不深究细节的情况下,这就是进程含义的全部了。
接下来展开细节,刨析进程的全部,可能就没你想的那么简单了。
什么是进程
我们写的程序就是一个存储在硬盘上的文件,经过编译后生成二进制可执行文件。
当我们运行这个可执行文件,首先需要把它加载到内存中,紧接着CPU就开始执行程序中的指令。
而正在运行的程序,就被称为进程(Process)。
如果你学过面相对象语言,听起来是不是很耳熟,存储在硬盘的程序就像是面向对象里的「类」,而进程就像是这个类创建的「实例」,也就是对象。
那现在考虑一个实际场景,假设你正在下载文件,下载的文件是需要存储到磁盘的。而磁盘的IO操作是很慢的,它的速度和CPU的执行速度差了几个数量级。
此时你的CPU是空闲状态的,难道就干等着磁盘下载完吗,那CPU的利用率会很低。
而且在用户视角表现出来就是,我在下载文件,这时候我想听歌,但还要等待下载完才能运行音乐软件。
这样用户体验也太差了。
误区:你平常同时开着浏览器、挂着qq、听着音乐,久而久之你可能都习以为常了,认为CPU同时能执行这些程序。实际上单核CPU同一时间只能运行一个程序,只不过CPU会在这些程序之间来回切换,这个速度可以达到纳秒级,所以给你一种同时运行这些程序的错觉。
举个生活中的简单例子,你去把食物放进烤箱,接下来你总不会傻等吧,这段时间可以去干别的事情,听到烤箱的提示音了,再去打开烤箱。
而「去干别的事」对应着CPU进程切换。
「听到烤箱提示音」对应着CPU收到中断请求,请回来继续执行这个进程。
所以,当用户下载文件时,不需要等待下载完成,可以去执行另外的程序,而下载完成后CPU会收到中断,再接着执行这个进程。
早期的批处理系统,其实就是单进程系统,同一时间执行一个进程,执行完了就接着执行下一个。
起初计算机就是拿来做数学运算,可以这样一个一个执行,后面的进程可以忍受前面的进程运行时间,一个一个排队,反正最后你给我运算结果就行了。
现在不一样了,交互式系统很看重响应时间,用户才不管你CPU现在在运行什么。
你CPU正在运算别的数据,我用户发来一个听音乐的请求,你就必须马上给我响应,哪怕CPU在运算很重要的数据,都要先保存当前状态,可以理解为存档,再切换到音乐进程,等到用户不需要了,再返回刚才那个进程的“存档”。
所以多进程系统就此诞生,只有一个CPU?没关系,操作系统给进程营造了一种假象,每个进程都可以有自己的CPU。
对于支持多进程的系统,CPU会从一个进程切换到另一个进程,每个进程各运行几十毫秒。
虽然在微观上CPU在某个瞬间只能执行一个进程,但在宏观上,它在多个进程之间不断切换,速度非常快,这样就产生了进程并行的错觉。
实际上这不是并行,而是「并发」。
![并发与并行](https://i-blog.csdnimg.cn/blog_migrate/281243749de15d64386bad2c82485ed7.png)
为什么需要进程
最一开始,是没有进程这个概念的。原因在于起初程序就是拿来做数学运算,输入一系列指令,运算,然后输出结果。
在这个过程中,这个程序是独占CPU的,后续有别的程序要运行的话,等这个程序运算完不就行了。
这个时期,程序在内存中是不「常驻」的,算完就清空内存,执行下一个程序。
而后来随着计算量的增大,程序也越来越多。发现程序在读取输入和打印输出的时候,其实CPU是空闲的,只有运算时CPU才运转。
而CPU在当时是很昂贵的,只有实验室和一些大学才有,当然要想办法提升CPU的利用率。
于是,在CPU等待进程1的输入或输出这个空闲时间,可以切换到进程2,这样CPU就一直保持运算状态。
![进程切换](https://i-blog.csdnimg.cn/blog_migrate/a71397b566a4b449aa00add1c665c6ff.png)
这就是进程的雏形。
后来诞生了一些恶意程序,想独占CPU使用权,通过恶意代码修改其他程序,让其他程序放弃CPU使用权。达到永久运行恶意程序的目的。
然后操作系统的设计者很自然的想到了「隔离」,一个程序不允许非法访问其他程序,而进程能防止程序免受恶意程序的修改。进程就像是这个程序自己的领地。
进程是怎样运行的
进程状态:
经过上面的讨论我们可以发现,进程的活动规律就是「运行-暂停-运行」。
所以,一个进程的活动期间至少具备三种状态,即运行状态、就绪状态、阻塞状态。
![进程状态切换](https://i-blog.csdnimg.cn/blog_migrate/3a9911e35c5ac9710948c14d43bc98e0.png)
各个状态含义:
- 运行状态(Running):此时进程占用CPU
- 就绪状态(Ready):此时进程可以被执行,但其他进程占用CPU,等待获取CPU使用权
- 阻塞状态(Blocked):此时进程正在等待某一事件完成,例如输入/输出。即使给它CPU使用权,它也不能运行
此外还有两种状态,创建状态(new)和结束状态(exit),对应着进程的创建&销毁。
进程的控制结构:
操作系统中使用进程控制块(process control block, PCB)这种数据结构来描述进程。
PCB存储的就是这个进程的所有信息,你可以理解为进程的个人资料。
具体包含为进程描述信息和进程控制信息,
进程描述信息:
- 进程标识符:每个进程都有唯一的标识,即进程的身份证号
- 用户标识符:这个进程属于哪个用户
进程控制信息:
- 进程的状态,比如running、ready、blocked等
- 进程优先级:进程获取CPU执行权的优先级
END
总的来说,进程就是对正在运行的程序的描述。
为了提升CPU利用率以及保证程序间的隔离,进程这个数据结构诞生了。
而CPU并发的执行进程,使得进程需要维护各种状态,以便在CPU上下文切换时可以准确无误。
我是「码农小奎」,欢迎扫码关注公众号,更多编程经验与经历想和你分享!