[Linux] Linux操作系统 进程的状态

 标题:[Linux] Linux操作系统 进程的状态

个人主页:@水墨不写bug​​​​​​​

(图片来源于网络)

目录

 一、前置概念的理解

1.并行和并发

2.时间片 

 3.进程间具有独立性

 4.等待的本质

二、特殊的进程状态

1.僵尸进程

2.孤儿进程


正文开始:

        在校的时候,你一定学过《操作系统原理》这本书,操作系统这个学科作为计算机哲学科目,无疑非常难以理解。再加上操作系统原理这本书并不是针对某一种操作系统而写的书,所以其内的大多数解释概念解释 含糊不清,难以琢磨

        这不是作者的原因,而是选题的原因:因为它讲的是操作系统这个抽象后的概念,对于某一种具体的操作无法落实到具体的事例,什么意思呢?

        比如,MacOS,Windows,Linux对于某一概念本质是一样的,但是处理方法不同,于是操作系统原理就笼统的用提取出来的概念来讲。再比如,模板大家都知道吧,《操作系统原理》这本书就好比是仅仅是对着模板来讲解,而不是一个具体的函数。一般而言,我们理解模板的正常逻辑是从一个具体函数然后上升到对模板的理解的,是从具体到抽象的过程,而不是仅仅停留在模板,只讲抽象的概念。

         这也就是你觉得操作系统难的原因。本文就沿着Linux这一具体的操作系统来讲解操作系统的概念。之所以选择Linux,是因为Linux是最受欢迎的高效、免费的操作系统,企业级应用最多。


         在理解进程的概念之前,我们需要先铺垫几个重要的概念:

 一、前置概念的理解

1.并行和并发

        并发:假设我们只有一个低配置的单核的CPU,这个时候我们仍然是可以启动多个进程的,为什么呢?这就是并发;

        CPU执行进程代码,不是把进程代码执行完,才开始执行下一个,而是给每一个进程预分配一个时间片,基于时间片,依次调度各个进程,进行调度轮转,这就是并发。即便只有一个CPU,这一个CPU仍然可以凭借并发,来在人眼无法分辨的时间段内极速切换,达到“同时”运行多个进程的目的。

        并行:多个进程在多个CPU下分别同时进行,称为并行


2.时间片 

        在Linux操作系统中,时间片(Time Slice)是操作系统进行  进程调度  时分配给每个进程运行的一段固定时间。Linux(以及许多其他现代操作系统)使用基于时间片的轮转调度算法(Round-Robin Scheduling)来管理CPU资源的分配,以确保所有进程都能公平地获得执行时间。

        当一个进程被调度到CPU上运行时,它会被分配一个时间片。在这个时间片内,进程可以执行其任务。当时间片结束时,无论该进程是否已经完成其工作,操作系统都会暂停该进程的执行,并将其放回就绪队列的末尾(或根据调度算法的其他规则重新排序)。然后,操作系统会选择另一个进程来执行,为其分配一个新的时间片。

        对于大多数民用级Linux/Windows操作系统,使用的是分时操作系统,也就是上面的这种采用时间片调度的操作系统。而对于一些特殊需求的高精度,高需求的场景:比如航空航天,车辆自动驾驶等,就不能再使用分时操作系统,因为毫秒级别的误差就可能导致事故。这些场景就需要采用实时操作系统


 3.进程间具有独立性

         进程间具有很强的独立性,这里目前不需要很深的理解。

        父进程创建的子进程挂掉之后,父进程不会收到影响,比如你在本地IDE上写一个程序,但是出现空指针导致程序挂掉了,你写的进程结束了,但是IDE不会因此挂掉。

 4.等待的本质

         在Linux下,进程有许多种不同的状态,之所以为进程区分状态,是为了提高效率。一个进程实际并没有用到CPU资源,但是却占用内存,这样的做法显然不合理。

        Linux进程的状态有:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

总体介绍:

        CPU根据一定的调度算法依次调度每一个进程。

        运行的或者是准备好的进程处于运行队列中。只要进程在运行队列中,该进城就处于运行状态,表示:“进程已经准备好了,可以随时被CPU调度进行运算”

        当一个进程被阻塞的时候,这个进程就不需要被放入运行队列中,因为它不需要被CPU调度。 那么这个进程就会被加载到不同的硬件的数据结构中,等待硬件的响应,这个时候的进程就处于睡眠状态。

        睡眠状态根据进程重要程度的不同,分为可中断睡眠和不可中断睡眠。

运行和阻塞的本质:

是让不同的进程处在不同的队列中。

       

 R运行状态(running) : 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。

S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))

D磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。

T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

X死亡状态(dead):这个状态只是一个返回状态,你无法在任务列表里看到这个状态

二、特殊的进程状态

1.僵尸进程

        僵尸进程就是一个进程一直处于Z状态,最终导致资源浪费的进程。当一个进程退出并且父进程没有读取到子进程的退出返回码时就会产生僵尸进程。

        僵尸进程会以程序终止状态保持在进程表中,并且会一直等待父进程读取退出代码。

        只要子进程退出,父进程还在运行,但是父进程没有读取到子进程的状态,子进程就会进入Z状态。

僵尸进程危害的原理

        进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于僵尸进程的状态。

        维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct中,换句话说, Z状态一直不退出, PCB一直都要维护。

        如果一个父进程创建了很多子进程,就是不回收,那么就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间。

        这就造成了系统层面上的内存泄漏。

2.孤儿进程

父进程如果提前退出,那么子进程后退出,进入Z之后,谁来读取子进程的状态呢?

        父进程先退出,子进程就称之为“孤儿进程”

        孤儿进程被1号系统进程领养,最终当然会被系统进程回收


完~

未经作者同意禁止转载

猜你喜欢

转载自blog.csdn.net/2301_79465388/article/details/142372453