目录
1 引言
2 操作系统的资源分配
3进程状态
3.1运行状态
3.2 阻塞状态
3.3挂起状态
4.进程状态详解
4.1 运行状态R
4.2 休眠状态S
4.3深度睡眠状态D
4.4僵尸状态Z
5 孤儿进程
6 进程优先级
其他概念
1 引言
🌻在前面的文章中,我们已经介绍了进程的概念,和如何取获取进程相关的属性及进程相关性的信息,以及如何去创建一个子进程。可是我们知道,系统中的内存资源是非常宝贵的,且系统中存在着大量的进程,对于这些进程,系统需要给其分配所需要的资源,对于如今的单核或者多核的计算机,想象一下,如果大量的进程同时需要进行处理,那么会产生什么样子的后果呢?
所以为了整个操作系统的稳定和效率,操作系统会对进程进行调度、管理,于是就需要对进程状态进行分类,操作系统需要知道哪些进程是可运行的,以便将它们分配给可用的CPU核心;哪些进程是睡眠的,这样可以将他们的内存页面换出到磁盘,释放内存资源等。
2 操作系统的资源分配
为了理解进程状态的概念,我们需要先理解一些操作系统进行资源分配的概念。
- 根据冯诺依曼体系结构,操作系统的设计就是向下为了与硬件交互,管理所有的软硬件资源,向上为用户提供一个良好的执行环境。那操作系统是怎么管理所有的硬件资源的呢?类似对进程的管理,操作系统会为每一个硬件维护了一个数据结构,用来存储他们的属性及相关信息。
- 而在描述每一个硬件的结构体中,一般都会存在一个用于给进程分配资源的等待队列。
- 当进程在执行中需要访问硬件设备时,即需要占用硬件设备资源的时候,操作系统就会将CPU队列中该进程的PCB拿出来放在该硬件的分配资源的等待队列中。
- 在硬件的分配资源等待的队列中,总是遵循先进先出的规则,硬件会给每一个在队列中排到队的进程分配资源,并不是只要在这个队列中就立即分配资源。
- 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
3进程状态
🌸在正式介绍进程状态之前,我们先说几个概念以助于理解进程状态:
- 一个CPU一个运行队列
- 让进程入队列的本质就是将该进程的task_struct结构体对象放入队列中
- 进程不止会等待(占用)CPU资源,也可能随时随地需要外设资源
- 所谓的进程的不同的状态,本质上是进程在不同的队列中等待资源
3.1运行状态
进程的运行状态并不是进程正在运行就叫运行状态,而是系统将进程的PCB放到CPU的分配资源的队列中等待运行的状态叫做运行态,无论进程是在排队还是在占用CPU资源。
3.2 阻塞状态
正在执行的进程由于发生某事件(如外设请求 )暂时无法继续执行,此时引起进程调度,操作系统会把需要与外设进行交互的进程拿出来与外设进行交互,把另一个进程放进cpu运行队列中,一般将这种状态称为阻塞状态。
3.3挂起状态
进程=PCB(内核数据结构)+磁盘中的代码
当一个程序运行的时候,程序的代码和数据会被加载到内存中,会占用内存的资源。对于系统中的一些短时间内不会被调度或者处于阻塞状态的进程,这些代码短时间内不会被运行起来,但是这些进程的代码和数据仍然在内存中,当内存空间不够时,操作系统会将这类进程暂时调离出内存,也就是将这类进程的程序和代码数据从内存中拿出来,放到指定的磁盘空间中,而将进程的PCB留在内存中。这样的操作称为进程的挂起。当之后条件允许的时候,这些代码和数据会被操作系统再次调回内存。
🌻挂起状态和阻塞状态的比较
相同点:1). 进程都暂停运行
2). 进程都释放CPU,即两个过程都会涉及到上下文的切换
不同点: 1). 对系统资源的占用:虽然都释放了CPU,但阻塞的进程仍处于内存中,而挂起的进程的代码和数据都已经被放入了磁盘。
4.进程状态详解
上述状态 是在宏观操作系统的层面上叙说状态,不同操作系统会有不同说法,接下来我们将演示一下Linux 操作系统的进程状态以及具体演示。如下是Linux 操作系统的不同状态。
4.1 运行状态R
我们写一个myprocess.c 的程序,其中是个循环,一直执行下去。
通过命令 ps ajx | head -1 && ps ajx | grep myprocess 命令我们可以看到当前进程状态。
通过上图我们能看到 STAT:R+ 即状态是运行状态。 (关于+后续说明)
4.2 休眠状态S
我们对myprocess.c 的程序进行改写,其中也是个死循环,一直执行下去,唯一不同的是我们进行了打印。
通过命令 ps ajx | head -1 && ps ajx | grep myprocess 看到当前进程状态。
我们发现当前状态STAT: S+,程序一直运行下去,不停的输出a的值为:4,进程的状态不应该是R+吗?
✍当cpu 运行myprocess 程序时速度是极快的,但是这里我们使用了printf()函数,即把数据打印在显示器上,所以这个进程需要与显示器进行交互,而与显示器交互的时间相比于cpu运行时间要长很多,所以此时操作系统会把myprocess这个进程从cpu的运行队列中拿出,去与外设显示器交互,然后再放到cpu运行队列中运行,所以说虽然这个进程一直在运行,但大多数时间都在与外设交互所以进程的状态是S状态。
4.3深度睡眠状态D
深度睡眠状态是不可中断的状态,是阻塞状态的一种,disk sleeping,说明该睡眠状态是跟dis(磁盘有关),指的是进程在等待磁盘资源时的阻塞状态。为什么有了睡眠状态S还要有一个深度睡眠状态D呢? 以及为什么深度睡眠状态要是不可中断的状态。
☻当我们需要输入一个很大的用户信息文件时候,需要向磁盘中传输数据,此时这个进程会在内存中与磁盘进行长时间的交互,即阻塞状态,当操作系统的内存空间不足的时候会进行挂起状态,但所挂起状态仍然内存资源不足的时候,系统会把这块内存释放掉,那么此时用户信息就会丢失,所以Linux操作系统有个深度休眠状态D,即不可中断状态。
4.4僵尸状态Z
Linux系统中的 X 状态,就是概念中的死亡状态,上面已经提到过当进程不会被调度、不会运行时,就会进入终止状态,此时该进程就等着被系统释放了。但是在Linux中,当进程不会再调度、不会再运行时,不会立马进入X状态,而是先进入Z(僵尸状态),此进程被称为僵尸进程Z
僵尸进程 Z的感性认识:进程被创建出来------->完成任务----------->要知道它完成的如何,可以不关心结果(进程退出的时候,不能立即被释放进程对应的资源,而是保存一段时间,让父进程或os来进行读取)------------------>进程进入死亡状态X被系统回收。
这里我们创建了一个子进程,子进程在5秒之后退出程序,但是父进程仍然会执行while循环,也就是说这个程序并没有终止,所以尽管子进程退出了但是因为这个程序还在运行,操作系统并没有对其释放,所以子进程将会是僵尸状态。
从上图我们可以看出刚开始子进程的状态是S+,即与显示器进行交互,后面子进程退出,但父进程还在执行,所以操作系统还没有对其回收,此时子进程的状态就为僵尸进程Z。
当我们终止进程的时候再进行查看状态的时候已经查不到了,因为进程被系统释放掉了
僵尸进程的危害:
- 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎 么样了。可父进程如果一直不读取,那子进程就一直处于Z状态。
- 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话 说,Z状态一直不退出,PCB一直都要维护。 那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费。因为数据结构对象本身就要占用内存
- 僵尸进程一直不被释放将会造成内存泄漏。
5 孤儿进程
- 父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?
- 父进程先退出,子进程就称之为“孤儿进程”
- 孤儿进程被1号init进程领养,1号init进程回收(1号int进程不是别的就是bash).
我们写个程序演示孤儿进程
我们能够看到父进程PID为18214
这一步我们把父进程18214 kill掉,明显能够看出子进程18215的父进程变成1而 1就是bash.,并且我们可以看到此时子进程被1进行收养之后,状态变成S,没有了+,这里的“+”表示是前台运行的意思,当子进程被1号领养之后,其状态就变为了后台运行。
☻此时子进程被1号进程领养之后,变成后台进程,用Ctrl + x并不能退出进程了,只能用kill + PID 杀死进程。
小结:
- 这种现象一定存在
- 子进程会被操作系统领养
- 为什么要这样做,如果不领养,那么子进程退出时,对于的僵尸,便没有人回收了。
- 被领养的进程-------------->孤儿进程
- 如果前台进程创建的子进程变成孤儿了,会自动变成后台进程。
6 进程优先级
进程优先级是什么?为什么需要有进程优先级?
进程优先级也是进程的一种属性,同样被包含在task_struct结构体中,其代表了CPU资源分配的先后顺序,优先权高的进程拥有优先执行的权利。
我们系统的资源是非常有限的,当出现大量的进程时,面对少量资源就不可避免地出现资源竞争的情况,类似现实生活中,如果系统不干预这种情况,任由进程自己竞争,则会出现部分进程执行不了自己的任务的情况,所以系统需要确定一个优先级,配置进程优先权对多任务环境的Linux很有用。
ps -l ps -al 可以查看进程的优先级PRI(priority优先级)NI(nice).Linux系统默认优先级为80
最终优先级 =老的优先级+nice.
Linux支持进程运行时,进行优先级调整,调整的策略就是更改nice完成。
知道进程的PID时, 进入top, 再按r, 再输入PID, 再输入需要的NI值, 就可以做到NI值的修改(必须为root用户)
- 不同程序界面的PRI值是不同的,可能是因为基准不同
- NI值是有自己的限度的,取值范围为-20到19
其他概念
- ✍竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高 效完成任务,更合理竞争相关资源,便具有了优先级
- ☝独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
- ✌并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
- ✆并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为 并发。