Linux:进程的状态理解

文章目录

  • 进程的理解
  • 僵尸进程
    • 僵尸进程的基本概念
    • 僵尸进程的演示
  • 孤儿进程
  • 进程的优先级概念
    • 优先级的更改
    • 对于优先级的理解
  • 其他边缘化的概念理解

进程的理解

前面对于进程的学习进行了理解,但是没有进行系统的总结

对于用户来说,为什么要创建一个进程?
因为要完成某种任务,而前面又知道,进程=代码和数据+内核数据结构,对于操作系统来说,内核数据结构是利用PCB来进行控制的,在Linux中,PCB具体叫做task_struct,而前面对于task_struct的源码也做了部分阅读,但并没有进行其他分析

那么进程的这两部分内容,都会在内存中占用一定的空间,而这些空间并不是被一直占用,当到达某个程度后,进程已经完成了自己的任务,这些内存就会被释放掉,进而操作系统将会管理其他的进程,进而进行控制

**进程的退出:**进程的退出意味着,将要释放掉自己的代码和数据

那么现在的问题是,进程是如何将自己已经完成的目的告诉操作系统?,其实也是借助了内核数据结构的功劳,从中也能看出,操作系统要进行进程的管理,必定是要对进程的数据进行管理,也能看出,管理的本质是管理数据,借助内核数据结构,操作系统可以很轻松的对进程进行管理,至于如何管理后续进行总结

僵尸进程

僵尸进程的基本概念

那么现在的问题是,操作系统确实可以在PCB中做标记,对于已经完成目的的进程,可以进行代码和数据的释放了,因此此时代码和数据就被通过某种手段释放掉了,但是此时的进程还不算被真正退出,因为还有PCB还留存在内存中,这个PCB是操作系统需要维护的,原因是这个进程的退出情况还没有被读取,还有存在的意义和价值,因此操作系统必须要对处于这种状态的进程做维护,直到父进程或者是其他控制管理的模块知道,这个进程退出了,不再需要这个进程的任何数据,这个进程才叫做真正的退出,但是如果一直不进行读取呢?

操作系统对于这样的进程,给了它一个状态表示叫做z状态,也叫做僵尸状态,而处于僵尸状态的进程就叫做僵尸进程,而处于僵尸状态的进程如果一直没有被回收,它会保持这个状态吗,答案是肯定的,操作系统会一直维护这个PCB结构,直到被读取后才能被真正的释放,PCB的状态也会随之从z状态改变为x状态,意味着这个进程真正意义上走到头了,可以被释放了

僵尸进程是有危害的,如果一直不对僵尸进程进行回收,它就会一直占用计算机内存中的存储空间,这样的行为就被叫做内存泄漏

僵尸进程的演示

下面对于僵尸进程进行演示,模拟一个会产生僵尸状态的场景

场景的模拟也很简单,创建两个进程,一个进程是另外一个进程的子进程,如果子进程终止了,但是父进程还在运行,此时父进程就不会对子进程进行回收,此时就是僵尸进程

那么进程代码的编写

# 完成Makefile的编写
cc=gcc
src=myproc.c
target=myproc 

$(target):$(src)
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f $(target)

实现一个程序,完成上面的功能:

#include 
#include 
#include 

int main()
{
    pid_t id=fork();
    if(id<0)
    {
        return 1;
    }
    else if(id>0)
    {
        // 父进程
        while(1)
        {
            printf("i am father\n");
            sleep(1);
        }
    }
    else 
    {
        // 子进程
        int cut=5;
        while(cut--)
        {
            printf("i am child:%d\n",cut);
            sleep(1);
        }
        printf("child dead\n");
        exit(2);
    }
    return 0;
}

上面这个程序就是使用了前面的思想,创建一个子进程,如果返回值是负数说明创建失败,如果返回值是0说明是子进程,如果返回值是其他说明是父进程,此时让子进程死亡,但是父进程还在循环

创建监视脚本:

# 监视带有myproc的进程
while :; do ps ajx |head -1 && ps ajx | grep process|grep -v grep; sleep 1;echo "###################################"; done

此时运行结果:

# 当程序运行5s后的结果
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
24154  1126  1126 24154 pts/0     1126 S+    1003   0:00 ./myproc
 1126  1127  1126 24154 pts/0     1126 Z+    1003   0:00 [myproc] <defunct>

从上面可以看出是符合一开始的与其结果的,子进程编号是1127,而父进程的编号是1126,此时子进程死亡后,父进程依旧在运行,没有机会回收子进程,此时子进程所处的状态就是Z,也就是所谓僵尸进程

孤儿进程

前面的代码中可以看出,子进程结束后,父进程没有及时回收就会进入僵尸状态,但如果子进程还没结束,父进程就结束了呢?

#include 
#include 
#include 

int main()
{
    pid_t id = fork();
    if (id < 0)
    {
        return 1;
    }
    else if (id ==0)
    {
        // 子进程
        while (1)
        {
            printf("i am child\n");
            sleep(1);
        }
    }
    else
    {
        // 父进程
        int cut = 5;
        while (cut--)
        {
            printf("i am father:%d\n", cut);
            sleep(1);
        }
        printf("father dead\n");
        exit(2);
    }
    return 0;
}

运行上面的程序,同时监视结果:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
24154 16031 16031 24154 pts/0    16031 S+    1003   0:00 ./myproc
16031 16032 16031 24154 pts/0    16031 S+    1003   0:00 ./myproc
###################################
 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
    1 16032 16031 24154 pts/0    24154 S     1003   0:00 ./myproc

从中可以看出一个现象,当父进程结束后,发生了两件事,父进程被回收了,同时这个父进程的子进程的ppid变成了1,同时程序变为后台程序运行

从中就引入了孤儿进程的概念:当子进程的父进程直接退出了,那么子进程就要被领养,变成孤儿进程,这个ppid1的进程被叫做是systemd initd进程

进程的优先级概念

什么是优先级?

优先级在实际的生产生活中也有具体的体现,比如在排队时,优先级高的可以优先获取到需要的资源,而在操作系统的层次上,对于进程也是如此,优先级高的进程,将会优先得到CPU分配的资源,而优先级高的进程还能够有优先执行的权利,配置进程的优先权对于Linux来说是很有用的,可以改善系统的性能

同时,也可以把进程运行到指定的CPU上,这样就能改善系统的整体性能

优先级的更改

Linux中,进程的优先级的值是由pri(old)+nice值来决定的,也就是说,用户只能通过修改nice值来进行对于优先级值的更变,而不管如何更改,最终程序的优先级的值一定是在一个区间内的,这样是有好处的,后续进行理解

对于优先级的理解

程序的优先级,实际上本质上是因为资源的不足,这是很好理解的,CPU在同一个时刻只能处理很少的数据,但是在同一时刻会有很多很多的进程等待,因此如何对于这些进程进行调度是很重要的一件事,才有了优先级的概念

进程的优先级本质上就是PCB中的一个数值,数值的范围是60-99,默认的进程优先级的值是80

为什么要把优先级设定在一定的范围?

这是由于要让程序被操作系统调度的时候,可以较为均衡的让每一个进程都得到调度,都能获取到资源,而不是优先级特别高的一直获取资源,而优先级较低的长时间都得不到资源,如果进程长时间都得不到资源,会产生一个问题,这个就叫做进程饥饿

其他边缘化的概念理解

竞争性:对于系统重的进程是有很多很多的,而CPU资源一般只有1个,因此优先级的诞生,就是要高效的完成任务,更加合理的进行相关资源的分配

独立性:进程之间的运行是不会相互干扰的,它们需要进行独立的享受各种资源

并行:对于需要进行比较大的数据处理时,会有多个CPU同时进行运转,而这个过程就被叫做并行的概念

并发:对于多个进程在一个CPU上运行的时候,就一定会不断地进行进程切换,而在同一个时间内,让多个进程都得到推进,这个就被叫做并发

你可能感兴趣的:(Linux,知识总结,linux,服务器,运维)