【Linux】进程状态、进程优先级和进程切换

> 作者简介:დ旧言~,目前大二,现在学习Java,c,c++,Python等
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:了解冯诺依曼体系结构与操作系统,掌握Linux的进程

> 毒鸡汤:一花凋零荒芜不了整个春天,一次挫折也荒废不了整个人生。

> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

🌟前言

        本篇博客基于学习完冯诺依曼体系结构与操作系统及其进程,进一步深度理解进程,学习完本篇对进程的理解会更上一层楼,想必大家已经按耐不住接收新的知识,那咱们话不多说进入今天的主题--->【Linux】进程状态、进程优先级和进程切换😳😳。

⭐主体

我们从以下学习【Linux】进程状态、进程优先级和进程切换🤗🤗。

🌙操作系统进程

        由于Linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序,就必然会产生很多的进程,而每个进程会有不同的状态。

        进程状态:一个程序被加载到内存变成进程之后,操作系统要对该进程进行管理,即为其创建对应的PCB对象,而进程状态,本质上就是PCB内部的一个整形变量,不同的整形值就对应不同的进程状态。

        常见的进程状态:运行、挂起、阻塞、新建、就绪、等待、挂机、死亡。进程的不同状态本质都是用来满足不同的运行场景的。

  • 运行队列

进程如何在CPU上运行的:CPU在内核上维护了一个运行队列,进行对进程的管理。让进程入队列,本质就是将该进程的task_struct 结构体对象放入运行队列之中。

一个CPU就一个运行队列

  • 进程状态
  1. 运行状态:

    进程PCB在运行队列里就是运行状态,不是说这个进程正在运行,才是运行状态。

    状态是进程内部的属性,所有的属性在PCB里

    进程不只是占用CPU资源,也有可能随时要外设资源

  2. 阻塞状态:

    进程不在运行队列之中,进程不能直接被调度,而是在等待外设资源的状态,进程的PCB就被放在硬件的等待队列中。本质是对tack_struct对象放到不同的队列中!

    综上,所谓的进程不同的状态,本质是进程在不同的队列之中,等待某种资源

  3. 挂起状态:

    如果系统中存在许多进程,进程短期内不会被调度,代码和数据在短期内不会被执行,此时如果内存空间不足,操作系统就可以把代码和数据暂时保存到磁盘上,节省一部分空间,该进程暂时被挂起了,这就是挂起状态。

    对于阻塞状态和挂起状态,阻塞不一定挂起,挂起一定是阻塞。

🌙Linux进程状态

我们Linux进程状态,可以用kernel源代码查看:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};
  • R运行状态(running) : 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。
  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
  • z僵尸状态(zombie):这个状态是一个已经运行完的子进程等待父进程回收它的返回信息。
     

那么我们可以亲自操作来查看各种状态

ps aux / ps axj //命令

那咱们看看Linux各种状态下的样子:

💫R运行状态 

创建Makefile:

创建myprocess.c:

#include<stdio.h>
#include<unistd.h>

int main()
{
	while(1);
	{
		int a = 0;
        a = 1+1;
	}
	return 0;
}

这里博主没有显示,因为没有运行。

💫S睡眠状态 

 创建Makefile:

创建myprocess.c:

#include<stdio.h>
#include<unistd.h>

int main()
{
	while(1);
	{
		int a = 0;
        a = 1+1;
	}
	return 0;
}

🌙两个特殊进程

进程退出的时候不能立即释放该进程对应的资源!保存一段时间,让对应的父进程/操作系统进行读取。

💫僵尸进程 

        进程退出了,但退出信息没有父进程或者OS被回收,那么此时该进程就处于僵尸进程。咱们演示一下效果。

创建myproc.c:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
    pid_t id = fork();
    if(id == 0)
    {
       // 子进程
            printf("after fork, 我是子进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
	    sleep(5);
	    exit(1);
    }
    else{
        // 父进程
        while(1){
            printf("after fork, 我是父进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
            sleep(1);
        }
    }
    return 0;
}

创建Makefile:

myproc:myproc.c
	gcc -o myproc myproc.c

.PHONY:clean

clean:
	rm -f myproc.c

运行结果:

总结:

  • 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程
  • 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。

僵尸进程的危害:

  • 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态?是的!
  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说, Z状态一直不退出, PCB一直都要维护?是的!
  • 那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费?是的!因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间!
  • 内存泄漏

💫孤儿进程 

父进程先退出,子进程就称之为"孤儿进程"

创建myproc.c:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    printf("before fork: I am a prcess, pid: %d, ppid: %d\n", getpid(), getppid());

    sleep(5);
    printf("开始创建进程啦!\n");
    sleep(1);
    pid_t id = fork();
    if (id < 0) return 1;
    else if (id == 0)
    {
       //  子进程
        while (1) {
            printf("after fork, 我是子进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
            sleep(1);
        }
    }
    else {
       //  父进程
        while (1) {
            printf("after fork, 我是父进程: I am a prcess, pid: %d, ppid: %d, return id: %d\n", getpid(), getppid(), id);
            sleep(1);
        }
    }
    return 0;
}

创建Makefile:

myproc:myproc.c
	gcc -o myproc myproc.c

.PHONY:clean

clean:
	rm -f myproc.c

运行结果:

🌙进程优先级

💫优先级概念

  • 优先级

即获取资源的先后顺序和先后被执行的能力。优先级高的先获得和执行,优先级低的反之。
存在的原因:资源太少,需要资源分配。

cpu资源分配的先后顺序,就是指进程的优先权(priority)。优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

  • Linux优先级

优先级本质就是PCB里面一个整数数字(或者几个整型数字)

Linux优先级有一个特点:很快

💫查看系统进程

在linux或者unix系统中,用ps –l/ps -al命令则会类似输出以下几个内容:

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  • NI :代表这个进程的nice值

💫PRI和NI

Linux中由两个整型数字决定优先级:PRI(priority)和NI(nice)

最终优先级 = 老的优先级(PRI)+ NI(nice)

注意:

        Linux下的老的优先级PRI默认值是80!而NI取值是有范围,取值范围是[-20,19]。也就意味着优先级是有取值范围的[80-21,80+19]

        在Linux下支持进程在运行中进行优先级调整的,调整的策略就是更改nice完成的,也就是说会受到nice值影响(但是一般情况下不修改),但是大部分情况下,nice值是默认的也就是0。

这里的PRI优先级是80,NI值是0

💫top命令更改nice

步骤1:sudo top

步骤2:进入top后输入r然后在输入进程的pid(进入进程)输入要修改nice的值

myproc.c代码:

初始NI和PRI:

用top命令进行修改:(先输入命令sudo top后在输入r,在输入进程的PID):

开始修改:(找到进程编号)

看到这个界面就可以开始更改NI值了:

这里博主就不修改了,但是要注意一些细节:

调优先级并不意味着你可以随便调,这是操作系统不允许的,会导致调度失衡。所以有着一定的取值范围

nice的取值范围是[-20,19],一共40个数字

  • 需要注意的是:每次调动优先级时候,PID值都会从默认值80开始,NI值从0开始,不存在累加累减情况。

💫特性

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发

这里的独立性对于父进程和子进程是否还是存在?yes

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        while (1)
        {
            printf("this is child process,pid: %d,ppid:%d\n", getpid(), getppid());
            sleep(1);
            int* p = NULL;
            *p = 100;//野指针
        }
    }
    else
    {
        while (1)
        {
            printf("this is parent process,pid:%d,ppid:%d\n", getpid(), getppid());
            sleep(1);
        }
    }
}

运行结果:

子进程崩溃并没有影响父进程。

💫进程切换

  • 1.并发
  • 多进程在同一CPU下通过采用进程不断切换的方式让一个单CPU计算机在一个时间段内同时让多个进程代码同时推进的现象称为并发
  • 采用进程切换的方式在一个时间段内不同的进程都可以把代码跑起来,同时推进

  • 2.进程如何切换
  • 一个CPU里面存在一套硬件寄存器,宏观上寄存器分为用户可见,用户不可见
  • 计算机调度某个进程时,CPU会把这个进程的PCB地址加载到某个寄存器,也就是说,CPU内有寄存器可以只找到进程的PCB地址
  • CPU里有一个eip寄存器(PC指针),指向当前执行指令的下一条指令的地址。

而进程运行的时候一定会产生很多的临时数据,但这些临时数据只属于当前进程,虽然CPU内部只有一套寄存器硬件,但是寄存器保存的数据只属于当前进程,也就是说,寄存器硬件不是寄存器内的数据,这是两码事,寄存器被所有进程共享,但是寄存器里的数据时每个进程各自私有的。

时间片引出:

  • 进程在运行的时候占有CPU,但是却不是一直占有到进程结束,进程都有自己的时间片!因为时间片的存在,进程会出现没有被执行完就被拿下去的情况,这时候问题来了:这个进程下一次如何在次回到CPU继续运行:
  • 进程切换的时候,需要先进行上下文保护,这里的上下文指的是CPU里的寄存器的数据,而不是寄存器,这里简单理解为临时数据保存至PCB里,而当进程恢复运行的时候,要进行上下文的恢复,该进程在次回到CPU继续运行时,重新加载恢复这些数据。

 🌟结束语

       今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/257035.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C : DS二叉排序树之删除(详细思路解答)

Description 给出一个数据序列&#xff0c;建立二叉排序树&#xff0c;并实现删除功能 对二叉排序树进行中序遍历&#xff0c;可以得到有序的数据序列 Input 第一行输入t&#xff0c;表示有t个数据序列 第二行输入n&#xff0c;表示首个序列包含n个数据 第三行输入n个数据…

机器学习:增强式学习Reinforcement learning

收集有标签数据比较困难的时候同时也不知道什么答案是比较好的时候可以考虑使用强化学习通过互动&#xff0c;机器可以自己知道什么结果是好的&#xff0c;什么结果是坏的 Outline 什么是RL Action就是一个functionEnvironment就是告诉这个Action是好的还是坏的 例子 Space i…

01-从JDK源码级别彻底剖析JVM类加载机制

文章目录 类加载运行全过程类加载器和双亲委派机制类加载器初始化过程双亲委派机制为什么要设计双亲委派机制&#xff1f;全盘负责委托机制自定义类加载器 打破双亲委派机制Tomcat打破双亲委派机制Tomcat自定义加载器详解模拟实现Tomcat的JasperLoader热加载 补充&#xff1a;H…

二进制枚举算法

二进制 : 也就是只有0和1的进制表示 ; 二进制枚举算法 一个二进制数 x 可以表示 S 的一个子集&#xff0c;某个二进制位i上为0表示没有选i元素&#xff0c;为1表示选了该元素放入子集,比如13为1101就表示选了0,2,3号元素;对于一个长度为N的序列(也就是包含N个元素)有2^N个子…

建筑模板怎么选?

在建筑领域&#xff0c;选择合适的模板材料对于确保工程质量、提高施工效率和控制成本至关重要。目前&#xff0c;常见的建筑模板主要有钢模板、塑料模板和木模板三种类型&#xff0c;每种都有其独特的优势和局限性。本文将对这些模板类型进行分析&#xff0c;并特别推荐广西生…

沉浸式数字文旅黑科技!用AI数字人升级景区体验

这年头文旅界也太卷了&#xff01; 在国家文化数字化战略的深入实施下&#xff0c;各地方文旅纷纷打造新型消费场景&#xff0c;以数字文旅提升消费产品的互动性和社交性&#xff0c;增强用户沉浸式体验。 其中&#xff0c;数字人乘着AI大语言模型的东风&#xff0c;被文旅品牌…

【数据结构】使用循环链表结构实现约瑟夫环问题

目录 1.循环链表的定义 2.约瑟夫环问题 3.创建循环链表 4.删除节点操作 5.打印所有节点 6.实现约瑟夫环问题的完整程序代码 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo_…

OpenAI 增强安全团队并赋予董事会对危险人工智能的否决权

OpenAI 在扩展其内部安全流程方面的举措以应对有害 AI 的威胁&#xff0c;OpenAI高层推出了一份更新的“准备框架”。OpenAI 的目标是识别、分析和决定如何应对他们正在开发的模型中的“灾难性”风险。他们通过对模型的四个风险类别进行评估&#xff0c;并根据风险级别制定相应…

在Android手机设置中启动ESIM

eSIM测试配置文件仅用于实验室测试。 1.到“设置”->“网络和互联网”->“SIM”&#xff0c;确认没有eSIM配置文件。 2.启动拨号程序&#xff0c;然后按短代码****#3746878#**#*&#xff08;****#ESIMTEST#**#**&#xff09; 有一个弹出通知“eSIM测试模式已启用” 3.返…

【JavaScript设计模式】Singleton Pattern

单例是可以被实例化一次的类&#xff0c;并且可以被全局访问。这个实例可以在整个应用程序中共享&#xff0c;这使得singleton非常适合管理应用程序中的全局状态。 首先&#xff0c;让我们看看使用ES2015类的单例是什么样子的。在这个例子中&#xff0c;我们将构建一个Counter…

ASP.NET MVC+EntityFramework图片头像上传

1&#xff0c;先展示一下整体的效果 2&#xff0c;接下来展示用户添加以及上传头像代码、添加用户界面 前端代码如下&#xff1a; <div class"form-group">Html.LabelFor(model > model.img, "头像&#xff1a;", htmlAttributes: new { class &…

【Linux】ip命令使用

ip命令 用于管理与配置网络接口和路由表。 ip命令的安装 ip 命令来自 iproute2 软件包&#xff0c;在 CentOS 7 中默认已安装。 yum install -y iproute 语法 ip [ OPTIONS ] OBJECT { COMMAND | help }ip [ -force ] -batch filename选项及作用 执行令 &#xff1a; ip …

计算机组成原理第4章-(存储器)【上】

存储器分类 对于计算机中存储器的分类&#xff0c;方法有很多&#xff0c;不同的方法之间是独立的&#xff0c;为此我们简单讲述两种分类 方法&#xff1a;“存取方式分类”、“在计算机中作用分类”。 -->按存取方式分类 按存取方式分类可以将存储器分为&#xff1a;“…

水经微图Web新版发布

水经微图Web新版已经上线&#xff0c;在该版本中主要新增了态势箭头标绘、文本要素标注和显示网页气泡等功能。 在本文中&#xff0c;我们将为大家分享新增的功能项&#xff0c;以及原有功能作的一些优化等。 当前版本 当前版本号为&#xff1a;1.4.0-beta 如果你发现该版…

JavaSE 泛型

目录 1 泛型类的定义1.1 为什么需要泛型1.2 泛型的概念1.3 泛型的分类 2 泛型类2.1 泛型类的定义2.2 泛型类的例子2.3 泛型类的实例化2.3.1 实例化语法2.3.2 裸类型(Raw Type) 2.4 泛型类的定义-类型边界2.5 泛型类的使用-通配符(Wildcards)2.5.1 基本概念2.5.2 通配符-上界2.5…

14、Kafka 请求是怎么被处理的

Kafka 请求是怎么被处理的 1、处理请求的 2 种常见方案1.1、顺序处理请求1.2、每个请求使用单独线程处理 2、Kafka 是如何处理请求的&#xff1f;3、控制类请求和数据类请求分离 无论是 Kafka 客户端还是 Broker 端&#xff0c;它们之间的交互都是通过 “请求 / 响应” 的方式完…

Hypervisor Display架构

Hypervisor Display架构部分 1&#xff0c;所有LA侧的APP与显示相关的调用最终都会交由SurfaceFlinger处理 2&#xff0c;SurfaceFlinger会最终调用android.hardware.graphics.composer2.4-service服务 3&#xff0c;android.hardware.graphics.composer2.4-service服务会调用G…

针对企业的泄密,天锐绿盾提出十大解决方案

01 防止公司内部数据泄密 通过动态加解密技术&#xff0c;有效防止公司内部数据泄密。即员工在创建、编辑文档时会被自动加密存放在硬盘上&#xff0c;防止员工故意或由于疏忽而造成泄密或对文件恶意破坏。 管理思路>> ● 不改变员工使用习惯、不改变文件格式、不改变…

APM固件编译和仿真

事情起因 主要想对无人机APM固件进行仿真的算法验证&#xff0c;因实际飞行的过程实际验证太浪费飞机了&#xff0c;所以就先试用仿真对算法进行仿真开发。 一&#xff0c;环境搭建 环境搭建我建议参考官方英文教程&#xff0c;英文教程写的比较全&#xff0c;不懂可以自己使…

科聪控制系统典型应用车型 —— 料箱机器人

料箱机器人即料箱AGV是一种智能化物流搬运设备&#xff0c;它可以代替人力完成出库入库和搬运工作&#xff0c;可根据出入库生产出货需求&#xff0c;将货物从起点运送到终点&#xff0c;自动柔性完成货到人货到点的操作。 提升仓储和物流效率的自动化利器 料箱机器人的投用能…