进程状态 + 进程优先级切换调度-进程概念(5)

文章目录

  • [Linux 具体的进程状态](#Linux 具体的进程状态)
    • [1. D(disk sleep)状态](#1. D(disk sleep)状态)
    • [2. X(dead)与 Z(zombile)状态](#2. X(dead)与 Z(zombile)状态)
    • [3. 如何模拟验证Z状态](#3. 如何模拟验证Z状态)
    • [4. slab 技术的补充](#4. slab 技术的补充)
  • 进程优先级切换调度(13-0.00.00)
    • [1. 孤儿进程](#1. 孤儿进程)
    • [2. 进程的优先级(13-0.25.00)](#2. 进程的优先级(13-0.25.00))
    • [3. 优先级的具体操作](#3. 优先级的具体操作)

Linux 具体的进程状态

1. D(disk sleep)状态

D状态被称作不可中断休眠或深度睡眠,可能跟磁盘有关系, 这里举个例子进行说明

现在有一个进程要写入100MB数据到磁盘,写入的过程中是有可能中断的,但无论如何,磁盘都会将写入结果返回给进程,进程再告诉用户。而磁盘在拷贝这100MB这份资源期间,进程啥也干不了,它要等磁盘的拷贝结果,此时进程就处于S状态。

但是当系统资源严重不足的时候,操作系统在极端的情况下会采取杀进程的方式释放空间(比如你手机软件有时会直接闪退),那如果这个进程被杀掉了,磁盘手里拿着这100MB的数据不知道该怎么办,跟进程讲也没有啥反应,就只好将其扔掉了,那在系统层面上就丢失了这100MB数据,而且用户还不知道

最为关键的是,操作系统,磁盘,进程,站在各自的角度看哪个都没有错。比如操作系统,它要不杀进程释放资源,那操作系统崩了,全部都得炸。进程它是直接被杀掉的,还是个受害者,没一点办法。磁盘委屈地说,我有啥问题,我都跟进程讲了,让它等我等我

所以此后就出现了D状态,当进程处于D状态时。操作系统就无权杀掉该进程,该进程也有权不对任何杀掉的动作进行响应

因此阻塞状态包括了两种:S与D,那这D状态就只能等它自己醒过来,或者直接重启,还有可能需要断电,才会将该进程直接杀掉

另外再补充一点其它的,输入命令:kill -l,可以查看能发送的信号,目前为止其中用的多是9(kill -9 进程UID),18,19。这三者分别是杀进程,进程继续,进程暂停

2. X(dead)与 Z(zombile)状态

X被称作死亡状态,也就是结束状态。Z被称作僵尸状态(zombile:僵尸),这里还是举个例子来帮助理解

你今天突然遇到一个人倒在了马路边,走上去用手感知,发现这个人没呼吸了,已经死了。这时你赶紧打110,说哪里哪里死了个人,警察来到现场后,会直接将尸体抬走并通知家属吗?

肯定是不会的啊,先封锁现场,让法医进行分析和解剖,直至法医获取到足够的信息,那在这段时间内这个进程所处的状态就是Z状态,就是为了获取进程的退出信息,当法官跟警察说通知家属,把人带走处理后事,这个人才真正死亡,也就是处于X状态

那为啥要存在僵尸状态呢?首先,我们创建子进程的目的是为了让进程完成某种事情的,那最后结果相关的信息(相关信息存储在task_struct中)父进程得知道吧

因此一个子进程要退出了,它并不是一退出就立马将PCB,代码和数据全部释放掉,当一个进程退出时,操作系统可以将这个进程的代码和数据全部释放掉,因为这个进程并不会被调度了

但是它的PCB信息是不能被释放的,必须将自己退出的信息暂时维持处,因为父进程需要从子进程的PCB里获取到子进程退出的结果

在子进程退出之后,父进程获取子进程退出信息之前,此时进程所处的状态就称之为Z状态

3. 如何模拟验证Z状态

创建父,子进程,让子进程在一定程度下直接退出,然后就能查到子进程退出后所处的状态

下面代码中,手动创建一个子进程,让子进程代码循环五次,自动结束。而父进程代码一直处于循环中,此时子进程已经退出了,而父进程仍在运行当中

c 复制代码
int main()
{
    pid_t id = fork();
    if(id == 0)
    {
        //child
        int count = 5;
        while(count)
        {
            printf("我是子进程,我正在运行: %d\n", count);
            sleep(1);
            count--;
        }
    }
    else 
    {
        while(1)
        {
            printf("我是父进程,我正在运行...\n");
            sleep(1);
        }
    }
    return 0;
}

从图片中也能看出,如果父进程一直不管,不获取子进程的退出信息,那么子进程就会一直处于僵尸状态,这样就会造成内存泄漏的问题,这个内存泄漏问题和下面内存泄漏问题造成的原因不同

在咱们写代码时,malloc或new出一片空间,但是忘记及时释放了,此时也会出现内存泄漏问题,那该进程退出了,内存泄漏问题还存不存在呢?不存在

进程一旦退出了,该内存泄漏的问题自然而然地就被解决了,也就是被自动回收了,而上面僵尸状态下的内存泄露的问题是系统层面上的,操作系统做不到回收该PCB

什么样的进程具有内存泄漏问题是比较麻烦的呢,常驻内存的进程 。常驻内存的进程:经常驻扎在内存中的进程,一旦启动该进程,基本上不会退出,一直死循环的那种(比如steam上的那个wallpaper软件)

4. slab 技术的补充

可以构建了一个unuse链表,原先的那个进程从Z状态变成X状态后,那个PCB不是要被释放吗?但是,我可以将要释放的PCB放到这个unuse链表中

等到后面操作系统要再创建(malloc)一个task_struct时,就能直接在这个链表中选择一个task_struct,将结构体里面的成员初始化,那这个task_struct结构体不就能够复用了吗

这样就形成了一个类似于内核当中的数据结构对象的缓存,所以在操作系统内它就可以加速我们创建进程和释放进程的速度,这种技术在Linux内核里叫做slab

进程优先级切换调度(13-0.00.00)

1. 孤儿进程

  • 父进程如果提前退出,那么子进程后退出,子进程进入Z之后,那该如何处理呢?
  • 父进程先退出,子进程就称之为孤儿进程
  • 孤儿进程被1号init/systemd进程领养,当然也要由init/systemd进程回收
c 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
   pid_t id = fork();
   if(id == 0)
   {
       // child
       while(1)
       {
           printf("我是一个子进程, pid: %d, ppid: %d\n", getpid(), getppid());
           sleep(1);
       }
   }
   else
   {
       // father
       int cnt = 5;
       while(cnt)
       {
           printf("我是一个父进程, pid: %d, ppid: %d\n", getpid(), getppid());
           cnt--;
           sleep(1);
       }
   }

   return 0;
}

父子进程关系中,如果父进程先退出,子进程就要被1号(操作系统)进程领养,这个被领养的子进程就叫做孤儿进程

那为什么要领养子进程呢?如果不领养的话,子进程进入僵尸状态之后,就没有父进程帮忙回收,此时就会造成内存泄漏问题

当进程变成孤儿进程,此时的进程就处于后台进程(./cmd &),从图片中也能看到子进程的状态从S+S

当该孤儿进程运行起来之后,命令ctrl + c就无法杀掉,也就是无法杀掉后台进程,同时后台进程能向前台打印消息

只能kill -9 孤儿进程的PID,这样才能将孤儿进程给杀掉

2. 进程的优先级(13-0.25.00)

  • 进程的优先级是什么 :进程得到CPU资源的先后顺序。这里将优先级和权限区分开来,权限是否能得到某种资源,优先级是一定能得到资源,只不过是先后的问题
  • 为什么会存在进程的优先级 :那进程为啥会在CPU上排队呢?因为目标资源稀缺,导致操作系统要通过优先级来确认谁先谁后使用资源的问题

3. 优先级的具体操作

优先级其实也是一种数字(int类型),task_struct的一种属性,值越低,优先级越高,反之优先级越低

基于时间片的分时操作系统,会考虑到公平性,也就是各进程优先级值要相差不大,优先级可能变化,但是变化幅度不能太大

UIDuser id,就是用户ID。人名是给用户看的,操作系统中是看UID,进程启动时会将UID给保存下来,记录这个进程是哪个用户启动的

用户跟操作系统打交道,都是通过进程来进行,用户所有的请求和任何都会转换成进程,被操作系统去调度和执行。所以识别权限并不是去识别用户的,是识别进程和文件之间的权限

带上选项n,显示出用户ID

那系统怎么知道我访问文件的时候,是拥有者,所属组,还是other呢?在Linux系统中,访问任何资源,都是进程去访问,进程就代表用户,OS它会拿着进程的UID依次去匹配文件的拥有者,所属组,other

相关推荐
basketball61613 分钟前
Linux C 管道文件操作
linux·运维·c语言
今天背单词了吗98018 分钟前
算法学习笔记:17.蒙特卡洛算法 ——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·笔记·考研·算法·蒙特卡洛算法
浩浩测试一下42 分钟前
Windows 与 Linux 内核安全及 Metasploit/LinEnum 在渗透测试中的综合应用
linux·运维·windows·web安全·网络安全·系统安全·安全架构
stark张宇1 小时前
Linux 文件创建、删除、移动、复制基础知识整理
linux·服务器·centos
逐花归海.1 小时前
『 C++ 入门到放弃 』- 多态
开发语言·c++·笔记·程序人生
致***锌1 小时前
期权交易完整版教程简介
笔记
棱镜研途2 小时前
学习笔记丨卷积神经网络(CNN):原理剖析与多领域Github应用
图像处理·笔记·学习·计算机视觉·cnn·卷积神经网络·信号处理
Jiangnan_Cai2 小时前
Linux 系统 docker 部署 Dify
linux·docker·大模型·dify
Two_brushes.3 小时前
【linux网络】深入理解 TCP/UDP:从基础端口号到可靠传输机制全解析
linux·运维·服务器
FJW0208143 小时前
【Linux】系统引导修复
linux·运维·服务器