进程概念、状态、优先级

💘作者:泠沫
💘博客主页:泠沫的博客
💘专栏:Linux系统编程,文件认识与理解…
💘觉得博主写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!
在这里插入图片描述

🏠 进程概念

无特殊情况下,笔者所述内容均是基于Linux操作系统环境下的。

🚀 进程控制块PCB

在介绍什么是进程之前,我们先来了解什么叫程序?

其实我们平时写代码编写好的程序本质上就是一个文件,一个安安静静的存放在磁盘上的文件。

一旦我们要运行这个文件,根据之前我们学过的冯诺依曼体系结构,我们知道一个程序要想被运行,首先要将代码和数据加载到内存当中。由于操作系统要将很多个运行起来的程序都管理起来,所以一旦程序对应的代码和数据加载到内存当中,操作系统会立即给这些运行的程序创建一个结构体struct task_struct{},这个结构体里面存放的是该运行程序的相关信息,而这个结构体也被称为进程控制块PCB。

如图是Linux源码中对进程控制块的部分描述:
在这里插入图片描述

如此,操作系统对这个运行程序的管理就转变成了对进程控制块做管理。所以笔者认为,真正的进程的指的是:内核数据结构(task_struct)+ 进程所对应的代码和数据。

操作系统对于进程的管理,转变成对于一个个的进程控制块的管理,这就是先描述,再组织思想的体现。

🚀 进程查看与标识符

进程查看方法一:

ps axj | head -1 && ps axj | grep myproc

其中 ps axj 表示查看所有进程,通过管道 | head -1 表示选择第一行,grep是搜索指令

在这里插入图片描述

上图是采用循环打印的方式来查看进程。

进程查看方式二:

在这里插入图片描述
系统中的进程会在 /proc 这个目录文件下,因此我们可以直接通过查看该文件的方式找到我们所要查看的进程。

如果读者细心观察会发现,我在/proc目录下查看进程的时候用的是一个数字。这个数字其实就是进程的唯一标识符。

进程并不存在进程名字这样的概念,操作系统是通过进程标识符来区分每一个进程的。

查看某一进程标识符的系统调用接口是getpid(),查看其父进程的接口是getppid()。
在这里插入图片描述

#include<iostream>
#include<sys/types.h>
#include<unistd.h>
 using namespace std;
 int main()
 {
    while(true)
    {
        cout << "我是一个进程,我的pid是:"<< getpid() << "我的父进程pid是:"<< getppid() << endl;
        sleep(1);
    }
    return 0;
 }

在这里插入图片描述

🚀 进程创建fork()

fork()是一个系统调用接口,其作用是创建一个子进程。

在这里插入图片描述在这里插入图片描述
该函数创建子进程成功返回值有两个!对于子进程,返回0。对于父进程,返回子进程的pid。所以我们可以根据返回值的不同来区分父子进程。

#include<iostream>
#include<cstdio>
#include<sys/types.h>
#include<unistd.h>
using namespace std;
int main()
{
    pid_t id = fork();
    if(id == 0)//子进程
    {
        while(1)
        {
             printf("我是子进程,pid:%d, ppid:%d\n",getpid(),getppid());
        }
    }
    //父进程
    while(1)
    {
        printf("我是父进程,pid:%d, ppid:%d\n",getpid(),getppid());
    }
    return 0;
}

在fork()调用之前,只有一个进程。在fork()调用之后,从原来的一个进程变成了两个进程。一个是父进程,另一个是子进程。对于fork()后续的代码,父子进程共享。

运行结果:
在这里插入图片描述
从上面的运行结果可以看出,父子进程各自执行自己的代码,死循环的打印语句。

🏠 进程状态

🚀 进程一般状态

Linux内核源代码:

在这里插入图片描述

  • R:指的运行就绪状态,也称为“运行中”状态。在R状态下,进程正在占用CPU资源并执行任务,处于活动状态。

  • S:指的是可中断睡眠状态。在S状态下,进程暂时停止运行,等待某些事件的发生。这些事件可能是IO操作(如等待文件读写的完成、等待网络数据的传输等),也可能是等待其他进程的信号或者定时器等。

  • D:指的不可中断睡状态,也被称为“休眠”或者“阻塞”状态。在D状态下,进程正在等待着一些事件的发生,这些事件一旦发生,进程就可以被唤醒并继续执行。和S状态不同的是,在D状态下,进程无法被中断,即使收到了终端信号都不会有反应。进入D状态的原因往往是进程在等待一些不可中断的IO操作的完成,如等待硬盘数据的读写、发送网络数据等。因为这些操作必须等待硬件设备的响应,所以即使进程收到终端信号也不能被中断。

  • T:指的是进程被暂停或等待某些事件的状态,也被称为停止状态。当进程收到SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU等信号时,它会进入到T状态。此外,如果一个进程在等待某个事件(如等待I/O操作完成或等待子进程结束),也会进入到T状态。

  • t:指的是进程被跟踪或调试的状态。这种状态只在特定情况下才会出现,如使用gdb工具进行调试时。

  • Z:指的是僵尸状态。 当一个进程的执行已经完成(即进程已经“死亡”),但是其父进程尚未从操作系统中获取其退出状态时,该进程就成为了“僵尸进程”。在这种情况下,内核将进程状态更改为“僵尸进程”,以表明它已经死亡,但仍然存在于进程表中,以便其父进程在适当的时间获得其退出状态。

  • X死亡状态。

  • P:指的是进程被挂起但仍然占有内存的状态。当进程因某种原因无法继续执行时,操作系统会将其挂起至P状态,并且将其从调度队列中移除,这样其他进程就能够利用CPU和其他系统资源。当有某种事件或信号到达时,操作系统会重新将进程唤醒,将其恢复至运行状态。

  • I:指的中断状态。当CPU接收到硬件或软件的中断请求时,会进入I状态,然后开始执行中断处理程序。中断可以来自于外部设备(如键盘、鼠标、打印机等),或由CPU自身的指令或异常引起。在I状态下,CPU会停止执行当前的任务,并转而去执行中断处理程序,处理完毕后再返回之前的任务。

🚀 Linux僵尸进程

这里是介绍僵尸进程及其危害,这是一个问题,但在此处不讲解如何解决。如果感兴趣的读者可以阅读笔者的进程控制文章,在那里僵尸进程会得到解决。
  • 僵尸进程的定义:
    僵尸进程指的是子进程先于父进程退出,且父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。

  • 僵尸进程的危害:
    僵尸进程需要占用系统中的进程表项和其他资源,可能会导致系统资源的浪费和耗尽,进而影响系统的稳定性和性能,甚至导致系统崩溃。僵尸进程如果不得到释放会造成内存泄漏。此外,如果系统中有大量僵尸进程存在,还会增加系统运维人员的工作量,降低系统的可维护性。因此,及时清理僵尸进程,释放系统资源,提高系统的稳定性和性能是很重要的。

  • 见识僵尸进程:

#include<iostream>
#include<cstdio>
#include<unistd.h>
#include<cstdlib>
int main()
{
    int a = 0;
    pid_t id = fork();
    if(id == 0)
    {
        while(true)
        {

        printf("I am child process, pid:%d, ppid:%d\n",getpid(),getppid());
        sleep(1);
        //exit(1);
         }
    }

    while(true)
    {        
        printf("I am parent process, pid:%d, ppid:%d\n",getpid(),getppid());
        sleep(1);
        //exit(-1);
        
    }
    return 0;
}

在这里插入图片描述

🚀 Linux孤儿进程

  • 孤儿进程的概念:

    孤儿进程指的是父进程先于子进程退出,但子进程还在运行。那么这些子进程会被pid为1的进程init(systemd)所收养,进而成为孤儿进程。

  • 见识孤儿进程:

#include<iostream>
#include<cstdio>
#include<unistd.h>
#include<cstdlib>
int main()
{
    int a = 0;
    pid_t id = fork();
    if(id == 0)
    {
        while(true)
        {

        printf("I am child process, pid:%d, ppid:%d\n",getpid(),getppid());
        sleep(1);
        //exit(1);
         }
    }

    while(true)
    {        
        printf("I am parent process, pid:%d, ppid:%d\n",getpid(),getppid());
        sleep(1);
        //exit(-1);
        
    }
    return 0;
}

在这里插入图片描述

孤儿进程被init收养后会从前台进程变为后台进程。

🏠 进程优先级

🚀优先级查看

在这里插入图片描述
进程优先级本质上就是一个整数,数字越小,优先级越高。
查看优先级的指令是:ps -al

🚀优先级更改

在Linux中,进程的优先级是可以允许修改的。

新的优先级 = 老的优先级 + nice值。Linux中就是允许修改nice值,进而对优先级进行修改。注意:这里的老的优先级默认一直是80。nice值的取值范围是[-20,19].

修改nice值的方法操作是:

  1. 先输入top命令。
  2. 进入top后按“r”–>输入进程PID–>输入nice值。

操作方式截图如下:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值