进程的状态和优先级

一.进程的退出

进程=内核PCB+数据和代码,它们都要占据内存空间,进程退出的核心工作之一就是释放掉自己的PCB+数据和代码。

为什么要创建出进程呢?一定是我要进程完成某些任务!

当进程退出了,不光光只是退出了这么简单,还要知道该进程把任务完成的怎么样吧,这里的你指的是谁啊?

一般指的是父进程或者OS,进程退出的时候,要有一些退出信息,表明自己把任务完成得怎么样了!

比如说平时我们写代码,给main函数的返回值都是return 0的,为什么这里我们要返回0呢?返回1,2,3等等行不行,

其实这里return 0就是一种退出信息,表示将任务完成的很好。(后续细说这个退出码)


进程退出了,退出信息会由OS写到该退出进程的PCB中,可以允许进程的代码和数据空间释放掉,但是它的退出信息还没有被父进程或OS读取到,OS就还必须维护该进程的PCB!

此时,该进程算是退出了吗?OS已经不会再调用该进程了,但是它的PCB确实还存在着,这时的进程就叫做僵尸进程。

二.Z(zombie)-僵尸进程

1.什么是僵尸进程?

僵尸状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲)

没有读取到子进程退出的返回代码时就会产生僵尸(死)进程。

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

所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

用代码来验证僵尸进程:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
 {
     pid_t id=fork();
     if(id<0)
          return 1;
      else if(id==0)//子进程
     {
       int ret=5;
       while(ret)
         {
            printf("I am child,run time:%d\n",ret--);
            sleep(1);
         }
        printf("I am child,dead!\n");
        exit(2);//进程退出(后续说)
    }
    else
    {                                         
        while(1)//父进程
       {
            printf("I am father,running any time\n");
            sleep(1);
       }
    }
    return 0;
 }

image-20240710154638161

可以很清晰的看见,当进程运行起来的时候,父子进程一起运行起来,当打印了五次之后,子进程退出了,但是父进程还在继续运行,父进程没有读取到子进程的退出信息,此时的子进程的状态就变成了Z+状态,也就是僵尸状态,此时的子进程也就变成了僵尸进程。

当进程变成了僵尸进程,就连kill -9也没办法杀死该进程,因为谁也杀死不了一个已经死了的进程。

2.僵尸进程的危害

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


维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话

说,Z状态一直不退出,PCB一直都要维护?是的!


那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构

对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!

内存泄漏?是的!

如何避免?后面讲

三.孤儿进程

当子进程退出了,父进程还没退出,父进程没有获取到子进程的退出信息,这时子进程就变成了僵尸进程。

然而孤儿进程恰恰是相反的,当父进程退出的时候,子进程还没有退出,这个时候的子进程就变成了孤儿进程了。

同样的我们还是使用代码来说明:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
 {
     pid_t id=fork();
     if(id<0)
          return 1;
      else if(id==0)//父进程
     {
       int ret=5;
       while(ret)
         {
            printf("I am father,run time:%d\n",ret--);
            sleep(1);
         }
        printf("I am father,dead!\n");
        exit(2);//进程退出(后续说)
    }
    else
    {                                         
        while(1)//父进程
       {
            printf("I am child,running any time\n");
            sleep(1);
       }
    }
    return 0;
 }

image-20240710162825346

image-20240710163215381

父进程的父进程是bash,这时毋庸置疑的,故而父进程退出的时候,它的退出信息被bash获取到了。

父进程使用fork创建出的子进程,父进程需要管理子进程的,但是子进程还在运行,父进程却已经退出了,子进程这个时候需要被领养,也就是被1号进程(init进程)领养,其实也就是OS。

四.进程的优先级

1.优先级的概念

  • cpu资源分配的先后顺序,就是指进程的优先级(priority)。

  • 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。

  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

OS中有很多进程需要调度,但是cpu就只有一个,那么这些进程就需要排队,排队的本质就是在确定进程的优先级。

2.为什么要有优先级?

举一个很简单的例子,像我们排队在食堂打饭的时候,为什么我们要排队呢?本质上就是窗口太少了,人太多了,资源分配不足。在OS中也是一样的,CPU只有一个,键盘只有一个,显示器只有一个,当很多进程都需要访问这些软硬件资源的时候,分配不过来,就需要指定哪些先执行,哪些后执行,这就是优先级的作用!!

3.查看系统进程

使用命令:**ps -l**查看系统中的进程。

image-20240710210106581

注意到几种重要的信息:

  • UID : 代表执行者的身份

  • PID : 代表这个进程的代号

  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号

  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行

  • NI :代表这个进程的nice值

4.操作优先级-修改NICE值

在linux中进程的优先级的范围为:60-99(一共四十个)。

默认进程的优先级都是80

其中优先级的数字越小,优先级越高。


其中通过nice值可以修改进程的优先级。

pri(新)=80+nice值。

修改步骤如下:

  • 使用命令top,进入任务管理器。

  • 然后在按“r”->输入进程的PID->输入nice值。

注意优先级的返回是有限制的。所以你输入再大或者再小的nice值,进程的优先级都会在60-99之间。

当你输入负nice值的时候,进程的优先级会变大,普通用户是做不到的,root账户才能做到。


为什么要将进程的优先级设置在一定范围呢?

OS调度进程的时候,要较为均衡的让每一个进程都要得到调度!

如果将进程可以设置为超级大,那么优先级小的进程,长时间得不到cpu的调度——进程饥饿。


其他概念

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。

  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。

  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。

  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值