文章目录
- 前言
- 一、进程切换
- 二、运行状态(R)
- 三、休眠状态(S)
- 四、磁盘休眠状态(D)
- 五、停止状态(T)
- 六、死亡状态(X)和僵尸状态(Z)
前言
人在做一件事情都会有对应的状态是做完了,还是没有开始做或者正在做,而进程也是有自己状态的进程对应状态:
这是一般操作系统的进程状态,其实操作系统进程状态都是差不多的,不过在Linuxx内核中进程状态分为:运行状态,休眠状态,磁盘休眠状态,停止状态,死亡状态,僵死状态。
一、进程切换
一个操作系统中注定会存在很多进程,然后去访问cpu的资源,那么这些进程是如何运行的,可不可以我某个进程对于cpu资源的访问是长久的,就是一直占用着cpu的资源,因为cpu资源只有一个,注定了进程之间是存在竞争关系的,对于资源的竞争,那么一个进程在cpu上运行,其他进程就只能等着这个进程运行完,但是若不加以限制,那么一个进程想长时间占用cpu资源,其他进程就会陷入一直等待由于有些进程长时间得不到cpu资源,就会饥饿然后会被饿死,这样操作系统一看不对啊,我让你进程执行某个功能,你死了还得了,他连忙修改进程对于cpu资源的访问机制,然后给每一个进程分配一个时间片信息,每个进程只能在cpu上访问规定时间,超过这个时间进程就会被替换下来,然后有其他进程访问cpu资源,而规定的这个时间是时间片(每个进程访问cpu资源的时间),最终在一个时间内,所有的进程都会被执行一遍,这样就展现了多个进程并发访问cpu资源的现象,其实都是一个一个访问cpu资源,只是时间太快根本无法察觉。而进程肯定不止只执行一次,因为可能他执行到它功能一半时它的时间片到了,然后他不得不被换下去,所有也注定了cpu上会存在大量进程被换出与放上去的动作,这个动作是进程切换。
二、运行状态®
当进程要放在cpu上运行的时候,肯定不止一个要运行,而是很多进程都要运行,那么如何保证他们要处于运行中,这在cpu中维护一个运行队列(struct runqueue)
struct runqueue
{
struct task_structhead;
struct task_structtail;
}
进程pcb内核数据结构以双链表形式组织,所有只需要将第一个进程链为head,最后一个链为tail,这样可以让进程进入运行队列中,进而若干进程在运行队列中进行排队,队列头部交给cpu运行,那么谁在cpu上运行谁没有在cpu上运行有一个调度器决定(根据进程优先级决定谁在cpu上运行)调度器能找到所有在运行队列中的进程,而在运行队列中的进程就是运行态!处于运行队列中的进程都是可以随时被运行的进程
这里运行状态是R+,为什么会有“+”号?,代表是在前台运行,此时在命令行输入指令相对来说是没有用的
而另外一个进程相当于后台进程
三、休眠状态(S)
计算机中底层存在各种设备也就是外设,而操作系统要对底层硬件做管理,用一种数据结构类型表示各种硬件,同样管理硬件也是先描述在组织。struct dev{…};其中有一重要字段信息pcb内核数据结构对象,因为外设要各自维护一个队列,当进程pcb内核数据结构加载好后,然后进程将对应信息写入pcb内核数据结构,但是当要写入数据的时候,若是要从键盘中读入数据,那么就要等待从键盘输入数据,但是键盘设备一直没有数据输入,那么这个进程就会一直在等待,在操作系统中,这样的进程可能会有很多,在等待各种设备就绪,然后从外设中读取数据或者将数据写进外设,进程会排队,那么这些进程在哪里排队?在对应所需对应设备维护的对待队列中排队,没错每个外设会给自己维护一个等待队列,因为设备可能忙不过来,可能刚好有进程正在使用外设但是又恰好有进程来了,你设备也不可能让他走,所有给它说我这里有个排队的地方,你去排队,一会就到你了,然后进程就乖乖去排队了。而处于设备维护的等待队列的进程它们处于一种对待的状态(也就是休眠状态),等到设备空了说,艾你可以去运行了,然后那个进程就立马去了,也就是处于休眠状态的进程可以被操作系统唤醒。
由于是休眠然后这个进程在等待,因此为S+状态,其实就算没有sleep,光是printf接口调用,几乎都会显示为休眠状态
同样表现为休眠状态,因为进程在cpu上执行特别的快,我们肉眼不可观察到,然后进程几乎所有时间都在等待显示器就绪,然后将数据写入到printf中显示出来,因此多数情况表现为S+
四、磁盘休眠状态(D)
当进程向磁盘中写入数据时,而磁盘也要在自己空间为进程拿来的数据找个地方写入,而写数据只有两种结果要么写入成功,要么写入失败,而磁盘对于写入的数据要返回一个结果给进程,在磁盘写入数据这个过程中,进程是在等待的,但是若是此时,操作系统内的进程已经是严重不足了,它巡视自己的所有进程,发现这个进程在这里闲着啥也不干,然后就决定把它给干掉,此时这个进程就被干掉,但是磁盘还在对于进程给的数据写入,若是磁盘发现要写入的数据写不下,太大了此时就会给进程返回写入失败,但是此时它返回结果没有进程接受,磁盘大概率会把数据丢掉,因为磁盘也有自己的事情要做,但是若是这数据又是很重要的,那么就会造成数据流失在这个过程中每个都各司其职谁也没有错,错的只有制度,在这个过程中进程被操作系统杀掉是它被唤醒然后接受了9号信号,而想要避免这样的情况发生,就不让他被唤醒就好了,让它将磁盘写入的数据拿到结果让他自然苏醒!进程这种状态叫做磁盘休眠也叫深度休眠状态。
五、停止状态(T)
T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
进程可以接收信号,通过kill -l可以查看所有信号,kill -对应进程信号编号 进程pid可以给进程发送信号,给进程发送19号信号可以让进程暂停,然后发送18号信号可以让进程从暂停状态中回复出来!
六、死亡状态(X)和僵尸状态(Z)
死亡状态就是进程没有了挂掉了,但是你不会在任务列表中看见这个状态,它是一瞬间的无迹可寻,死掉就死掉了!但是一个进程死掉之后他还会留有一些信息,会保存下来,会等待别人来回收它身上的信息。就像电影里面的那些锦衣卫办案一样,当一个人在大街上忽然倒地时,肯定有人报案然后锦衣卫迅速赶到将现场保存维护起来,等待法医鉴定死亡结果,之后再通知家属认领,才可以拿回去。进程当然不用这么多流程,但是一个进程死亡时,也是要将它的信息保存下来,然后一直保留着知道它的父进程来回收它的信息,而进程死亡之后将信息(pcb)保存下来这一个持续状态,为僵尸状态!它要一直保存进程pcb数据结构对象,然后直到它的父进程来回收它子进程的pcb,才会释放这个进程的pcb数据结构中所含字段信息,若是父进程一直不来回收它或者是忘记回收了,那么就会造成这个挂掉的进程一直在吃操作系统的内存资源,当不释放时就会进而引起内存泄漏问题,而解决方法可以让父进程等待子进程的退出(死亡)然后解决内存泄漏。
子进程退出了但是父进程还在运行,且不回收子进程所有它的子进程就会一直处于Z状态,但是若是有一天子进程还在运行的时候夫进程却退出了,那么就没有人来回收它,会就变成了孤儿进程了。
当没有人回收时,那么此时操作系统就要上场了,这个进程的父进程就变成了1号进程,总归要有人来管理回收这个进程不然真的造成内存泄漏得不偿失!所有没有父进程的进程就会由操作系统来接管,这个进程的父进程就变为了1号进程,而这种父进程比子进程先退出的进程,它由别的进程接管叫做孤儿进程!(我这刚刚是卡着了给这个孤儿进程发信号它都不理我,哈哈)