Linux:进程的状态理解

简介: 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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
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上运行的时候,就一定会不断地进行进程切换,而在同一个时间内,让多个进程都得到推进,这个就被叫做并发

相关文章
|
1月前
|
资源调度 Linux 调度
Linux c/c++之进程基础
这篇文章主要介绍了Linux下C/C++进程的基本概念、组成、模式、运行和状态,以及如何使用系统调用创建和管理进程。
35 0
|
3月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
640 2
|
3月前
|
Linux Python
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
67 2
|
16天前
|
缓存 监控 Linux
linux进程管理万字详解!!!
本文档介绍了Linux系统中进程管理、系统负载监控、内存监控和磁盘监控的基本概念和常用命令。主要内容包括: 1. **进程管理**: - **进程介绍**:程序与进程的关系、进程的生命周期、查看进程号和父进程号的方法。 - **进程监控命令**:`ps`、`pstree`、`pidof`、`top`、`htop`、`lsof`等命令的使用方法和案例。 - **进程管理命令**:控制信号、`kill`、`pkill`、`killall`、前台和后台运行、`screen`、`nohup`等命令的使用方法和案例。
48 4
linux进程管理万字详解!!!
|
6天前
|
存储 运维 监控
深入Linux基础:文件系统与进程管理详解
深入Linux基础:文件系统与进程管理详解
43 8
|
15天前
|
算法 Linux 定位技术
Linux内核中的进程调度算法解析####
【10月更文挑战第29天】 本文深入剖析了Linux操作系统的心脏——内核中至关重要的组成部分之一,即进程调度机制。不同于传统的摘要概述,我们将通过一段引人入胜的故事线来揭开进程调度算法的神秘面纱,展现其背后的精妙设计与复杂逻辑,让读者仿佛跟随一位虚拟的“进程侦探”,一步步探索Linux如何高效、公平地管理众多进程,确保系统资源的最优分配与利用。 ####
48 4
|
16天前
|
缓存 负载均衡 算法
Linux内核中的进程调度算法解析####
本文深入探讨了Linux操作系统核心组件之一——进程调度器,着重分析了其采用的CFS(完全公平调度器)算法。不同于传统摘要对研究背景、方法、结果和结论的概述,本文摘要将直接揭示CFS算法的核心优势及其在现代多核处理器环境下如何实现高效、公平的资源分配,同时简要提及该算法如何优化系统响应时间和吞吐量,为读者快速构建对Linux进程调度机制的认知框架。 ####
|
17天前
|
消息中间件 存储 Linux
|
24天前
|
运维 Linux
Linux查找占用的端口,并杀死进程的简单方法
通过上述步骤和命令,您能够迅速识别并根据实际情况管理Linux系统中占用特定端口的进程。为了获得更全面的服务器管理技巧和解决方案,提供了丰富的资源和专业服务,是您提升运维技能的理想选择。
25 1
|
1月前
|
算法 Linux 调度
深入理解Linux操作系统的进程管理
【10月更文挑战第9天】本文将深入浅出地介绍Linux系统中的进程管理机制,包括进程的概念、状态、调度以及如何在Linux环境下进行进程控制。我们将通过直观的语言和生动的比喻,让读者轻松掌握这一核心概念。文章不仅适合初学者构建基础,也能帮助有经验的用户加深对进程管理的理解。
22 1