【Linux】进程状态|优先级|进程切换|环境变量

news2024/11/23 6:48:16

文章目录

  • 1. 运行队列和运行状态
  • 2. 进程状态
  • 3. 两种特殊的进程
    • 僵尸进程
    • 孤儿进程
  • 4. 进程优先级
  • 5. 进程切换
    • 进程特性
    • 进程切换
  • 6. 环境变量的基本概念
  • 7. PATH环境变量
  • 8. 设置和获取环境变量
  • 9. 命令行参数


1. 运行队列和运行状态

💕 运行队列:

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

在这里插入图片描述

💕 运行状态:

  • 运行状态 进程PCB在运行队列里就是运行状态,不是说这个进程正在运行,才是运行状态。状态是进程内部的属性,所有的属性在PCB里,进程不只是占用CPU资源,也有可能随时要外设资源。
  • 阻塞状态 进程因为等待某种条件就绪而导致的一种不推进的状态——进程卡住了,此时的进程要通过等待的方式,等待具体的资源被别人用完之后,再被自己使用。阻塞状态进程的PCB被放在硬件的等待队列中。本质是对tack_struct对象放到不同的队列中!
    在这里插入图片描述
  • 挂起状态 如果系统中存在许多进程,进程短期内不会被调度,代码和数据在短期内不会被执行,此时如果内存空间不足,操作系统就可以把代码和数据暂时保存到磁盘上,节省一部分空间,该进程暂时被挂起了,这就是挂起状态。对于阻塞状态和挂起状态,阻塞不一定挂起,挂起一定是阻塞。
    在这里插入图片描述

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


2. 进程状态

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在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):这个状态是一个已经运行完的子进程,等待父进程回收他的返回值。

💕 运行状态R

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

💕 睡眠状态S

在这里插入图片描述

当我们执行可执行程序后,在使用ps命令查看进程状态时,发现他是S状态,为什么我们的程序正在运行,进程却是睡眠状态呢?

在这里插入图片描述

这是因为我们使用printf进行打印时,需要访问外设,但外设的速度是远远低于CPU的,所以进程大部分时间都在等待硬件资源的就绪,所以我们每次查看时,进程几乎都处于阻塞状态。

💕 磁盘休眠状态D

当内存中的空间不足时,操作系统会让一些进程进入挂起状态,但是,如果内存的空间严重不足时,进程挂起也解决不了问题,这个时候操作系统可能会将一些暂时挂起的进程或者没有被调度的进程杀掉。

但是如果要是此时挂起的进程正在向磁盘写入数据,或者进行一些重要的数据传递时,如果操作系统将这个进程杀死,那么磁盘就可能会将正在传递的数据丢弃,此时重要的数据就有可能因为操作系统将进程杀死导致重要数据的丢失。所以,我们的深度睡眠状态就是针对这种情况而生的。深度睡眠状态下的进程既不能被用户杀死,操作系统也无法将其杀死。只能通过断点,或者等待进程自己醒过来。

💕 暂停状态T

暂定状态也是阻塞状态的一种,下面我们来看一下如何让一个运行状态下的进程暂停:

在这里插入图片描述

我们可以使用kill的19号指令将一个进程从运行状态变为暂停状态。

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

如果想要使得休眠中的进程重新恢复运行状态只需要执行kill的18号命令即可:

在这里插入图片描述

这里我们可以看到进程又重新进入了运行状态,但是为什么进程重新进入云心状态后后面的 +号 消失了呢?

其实,进程状态后面的 +号 表示的是这个进程是一个后台进程,如果没有 +号就表示这个进程是一个前台进程。对于前台进程我们可以使用Ctrl + c将其杀死,但是对于后台进程,我们只能使用kill命令杀死他。

💕 追踪暂停状态t

属于暂停状态的一种,表示进程正在被追踪。最典型的一种就是gdb调试进程的时候。

💕 死亡状态X

表示一个进程结束运行,他的PCB以及代码和数据全部都被操作系统回收。

💕 僵尸状态Z

一个进程在退出的时候,不能立即释放全部的资源,但是该进程已经不会再被执行了,该进程的PCB中存放着他的各种各样的状态码,尤其是退出状态码。

僵尸状态就是为了在进程退出的时候能够让父进程或者操作系统拿到他退出状态码,然后释放PCB的一种状态。


3. 两种特殊的进程

僵尸进程

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

下面我们来举例看一下僵尸进程:

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

当我们杀掉子进程后,由于父进程并没有读取子进程的退出状态码,所以子进程进入了Z(僵尸状态),如果父进程一直不读取子进程的退出状态码,那么子进程就会变成僵尸进程

在这里插入图片描述

僵尸进程的危害:

父进程如果一直不读取子进程的退出状态码,那子进程就一直处于Z状态。维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中。换句话说, Z状态一直不退出, PCB一直都要维护。那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费。


孤儿进程

父进程如果提前退出,那么子进程就会被操作系统领养,此时的子进程就称之为“孤儿进程”,孤儿进程被1号init进程领养,最后由init进程回收。

在这里插入图片描述

这里我们可以看到:如果将父进程杀死后,父进程并不会进入僵尸状态,这是因为父进程在退出后会被父进程的父进程——bash所读取他的退出状态码。还有子进程被1号进程领养后会由前台进程变成后台进程。


4. 进程优先级

CPU的资源是有限的,但是内存中有很多进程都需要占用资源,所以需要给进程指定优先级来合理的分配资源。

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

在这里插入图片描述

当我们输入ps -l/ps -al指令后就可以看到进程优先级相关的属性:

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :该进程的父进程的代号
  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  • NI :代表这个进程的nice值

下面我们重点介绍一下PRINI这两个变量,PRI(priority) 即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。而NI(nice) 表示进程可被执行的优先级的修正数值。需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正修正数据。

PRI值越小越快被执行,那么加入NI值后,将会使得PRI变为: PRI(new)=PRI(old)+NI,这里我们需要注意的是:每个进程默认的PRI都是80,NI都是0,但是NI的波动范围是:[-20,19],PRI与NI的和越小,进程的优先级越高。

下面我们来看一下如何修改进程的优先级:

(1) 输入top指令

在这里插入图片描述

(2) 输入r

在这里插入图片描述

(3) 输入进程的id

在这里插入图片描述

(4) 输入NI值

在这里插入图片描述

这里我们还需要注意的是:普通用户无法直接修改NI的值,必须切换成root用户或者使用sudo提权执行top指令。


5. 进程切换

进程特性

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

进程切换

一个CPU里面存在一套硬件寄存器,宏观上寄存器分为用户可见,用户不可见。

计算机调度某个进程时,CPU会把这个进程的PCB地址加载到某个寄存器,也就是说,CPU内有寄存器可以只找到进程的PCB地址。

CPU里有一个eip寄存器(PC指针),指向当前执行指令的下一条指令的地址。

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

时间片引出——进程在运行的时候占有CPU,但是却不是一直占有到进程结束,进程都有自己的时间片!因为时间片的存在,进程会出现没有被执行完就被拿下去的情况,这时候问题来了:这个进程下一次如何在次回到CPU继续运行:

进程切换的时候,需要先进行上下文保护,这里的上下文指的是CPU里的寄存器的数据,而不是寄存器,这里简单理解为临时数据保存至PCB里,而当进程恢复运行的时候,要进行上下文的恢复,该进程在次回到CPU继续运行时,重新加载恢复这些数据。


6. 环境变量的基本概念

环境变量(environment variables) 一般是指在操作系统中用来指定操作系统运行环境的一些参数。

  • 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。

当我们平常执行自己的可执行程序时,必须在前面指定路径来执行,但是执行Linux中的指令时,并不需要指定路径,这是什么原因呢?

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

其实,在Linux下的各种指令和我们平常自己编写代码生成的可执行程序没有什么区别,他也是个可执行程序,但是因为系统中存在PATH环境变量,这些指令的地址都被存放在环境变量中,当我们调用这些指令时,系统会自定去PATH中寻找这些指令。


7. PATH环境变量

PATH是由一堆目录组成的,各目录之间用冒号 “:” 隔开。 当执行某个 Linux 命令时,Linux 会依照 PATH 环境变量中包含的目录依次搜寻该命令的可执行文件,一旦找到,即正常执行;反之,则提示无法找到该命令。

💕 查看环境变量:echo $PATH

在这里插入图片描述

💕 添加PATH环境变量:

(1) 直接添加

在这里插入图片描述

一般不建议使用这种方法添加,因为我们写的程序没有经过测试,容易污染指令池。

(2) 使用export命令添加

在这里插入图片描述

在这里我们还需要注意的是,我们不能直接写成这样:export PATH=/home/Chenjiale/lesson2-22,这样会导致把系统默认的环境变量PATH覆盖掉,我们默认的那些指令就不能直接使用了,只能通过指定路径的方式来使用。

💕 系统中的其他环境变量:

  • HOSTNAME: 主机名
  • USER: 当前用户名
  • PWD: 当前系统路径
  • HOME: 当前用户的家目录
  • HISTSIZE: shell 能记忆的最多历史命令的条数

查看所有的环境变量:env指令

在这里插入图片描述

下面我们来看一下环境变量是在系统中的哪个文件夹下面的:

在这里插入图片描述

实际上,当我们在登录 shell 时,操作系统会让我们当前的 shell 进程执行 .bash_profile 中的内容,而 .bash_profile 又会调用执行 .bashrc,它们会将对应的环境变量导入到 shell 进程的上下文环境中。所以,如果我们上面不小心将 $PATH 覆盖掉了也不用担心,重新登录 shell 就好了。

环境变量是操作系统为了满足不同的应用场景,预先在系统内设置的一大批全局变量,这些变量往往具有特殊功能,且能够一直被 bash 以及 bash 的子进程访问。环境变量具有全局属性的根本原因是环境变量会被子进程继承。


8. 设置和获取环境变量

💕 设置和取消环境变量:

如果我们直接在命令行中定义一个变量,那么这个变量则是本地变量,本地变量只在bash进程中有效。

在这里插入图片描述

当然我们可以使用export直接将本地变量设置为环境变量,同时,也可以直接使用export来定义一个环境变量。

export 已存在的环境变量 将本地变量设置为环境变量

export 新的变量 直接定义一个环境变量

在这里插入图片描述

如果我们不想要这个变量,可以直接使用unset指令来取消变量,当然我们也可以使用set指令来查看所有变量。

在这里插入图片描述

💕 获取环境变量:

获取环境变量除了可以使用echo $环境变量名之外,还可以使用一个函数getenv()来获取。

在这里插入图片描述

下面我们举例来演示一下:

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

在命令行上运行mytest时候,bash就是一个系统进程,mytest也会变成一个进程(通过fork创建父子进程),是bash的子进程。而环境变量具有全局属性的根本原因是会被子进程继承下去,因为环境变量定义给bash,而子进程会全部继承下去,这就被称为环境变量。所以环境变量具有全局性,而本地变量只会在当前进程(bash内)有效。

为了不同的应用场景,让bash替我们寻找指令路径,例如:身份认证;有些子进程需要用到这些信息,确认当前用户的信息。

下面我们来举一个例子:

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

这里我们一定要使用su -来验证,我们可以使用getenv函数来获得当前的Linux用户,判断其是否具有某种权限,然后再执行对应的操作。


9. 命令行参数

我们知道在C语言中,main函数也是有参数的,不过我们平常一般都不需要手动传参,而是被系统/父进行行传参的。所以,这个参数可能会被大多数人忽略。

int main(int argc,char* argv[],char* env[])

这里我们可以先来看一下前两个参数,第一个参数是指第二个参数——指针数组中的元素个数。这里我们可以先来看一下指针数组中的每一个元素存的是什么。

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

其实这里的argv中的每一个元素都指向的是一个字符串,argc用来指定数组中元素的个数,他们配合可以使用-a -b -c 类似的选项功能。

下面我们来看一下最后一个指针数组中的内容:

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

这里我们看到的是:打印出来的就是环境变量的内容。这是因为env接收的就是父进程传递过来的环境变量的参数。

最后,还有一种获取环境变量内容的方式就是通过环境变量表environ,这里我们直接来验证一下即可。

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


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在Net6.0里配置多版本支持并支持注释说明的Swagger

一、前言现在已经进入了微服务的开发时代了,在这个时代,如果有人问你什么是微服务,你说不知道,就有点太丢人了,别人会有异样的眼光看你,俗话说:唾液淹死人。没办法,我们只能去学习新…

一款 Linux、数据库、Redis、MongoDB 统一管理平台,这个开源平台非常好用!

一、开源项目简介基于DDD分层实现的web版 linux(终端 文件 脚本 进程)、数据库(mysql postgres)、redis(单机 集群)、mongo统一管理操作平台二、开源协议使用Apache-2.0开源协议三、界面展示(系统核心功能截图)四、服务部署&#…

Windows 平台 oracle11g 单机 打补丁(33883353)

一、从oracle官网下载最新补丁包和打包工具 二、 对数据库及软件作全备 略 三、解压p33883353_112040_MSWIN-x86-64.zip 在33883353文件夹中打开README.html 2.1 OPatch Utility You must use the OPatch utility version 11.2.0.3.34 or later to apply this patch. 必须…

Maven 依赖-镜像仓库替换为 -- 阿里云镜像仓库(飞快实现 pom 引入)

在本地 maven 的 setting 配置文件中加上阿里云镜像地址就行了&#xff1a;新增配置内容&#xff1a;<!-- 阿里镜像仓库 --><mirrors><mirror><id>alimaven</id><name>aliyun maven</name><url>http://maven.aliyun.com/nexus…

高项--十大管理、47个过程、五大过程组

十大管理、47个过程、五大过程组【联想记忆】 文章目录 十大管理、47个过程、五大过程组【联想记忆】 十大管理 1.十大管理是哪几个&#xff1f; 2.十大管理记忆口诀&#xff1a; 3.各大管理记忆口诀&#xff1a; 4.十大管理、十大管理的47个过程、47个过程所属的五大过程组&a…

一篇文章搞定linux网络模型

网络协议感觉晦涩难懂&#xff1f;什么七层网络模型&#xff1f;又五层网络模型&#xff1f;又四层网络模型&#xff1f;TCP/IP协议是个啥&#xff1f;UDP是啥&#xff1f;什么是三次握手&#xff1f;什么是四次挥手&#xff1f;tcpdump听说是抓包的&#xff0c;怎么用&#xf…

期末综合考试

一、概率论1、全概率公式、贝叶斯公式应用2、期望、方差、协方差的定义以及性质证明(1) 期望(2) 方差(3) 协方差二、数理统计1、参数估计(1) 矩估计(2) 最大似然估计(3) 综合例题一、概率论 1、全概率公式、贝叶斯公式应用 记住标黄的两段&#xff0c;上考场直接套数据&#x…

相交链表【2.23】

题目&#xff1a;给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;…

SYSU程设c++(第一周) io流、命名空间、引用

理论题&#xff1a; 1.std::cout<<0a; 的输出是97 &#xff08;0转换了类型成int&#xff0c;‘a变成askll码&#xff09; 2.std::cout<<0"12.34";的输出是12.34 &#xff08;0无用&#xff0c;忽略) 3.std::cout<<1"12.34";则编译错…

批量修改word中的表格属性

背景&#xff1a;写接口文档&#xff0c;程序导出的接口文档格式不符合标书的需要&#xff0c;要批量设置word表格及文本————————————————————————————————方法&#xff1a;我们可以通过word的宏观能&#xff0c;实现批量设置。1说明&#xff…

表格内容过多时单行/多行显示

分析 单行多行显示涉及到 table-layout: fixed; 这个属性&#xff0c;默认状态下的属性值是 auto &#xff08;自动表格布局&#xff09;&#xff0c;两种不同的属性值区别如下&#xff1a; 方法 我在设置表格内容单行/多行显示时采用的方法&#xff1a; table 添加的样式&a…

JS - 原型对象、原型链是什么

一 阅读掘金 https://juejin.cn/post/7007416743215759373 https://juejin.cn/post/7007416743215759373 二 阅读掘金小册原型知识点 原型 涉及面试题&#xff1a;如何理解原型&#xff1f;如何理解原型链&#xff1f; 当我们创建一个对象时 let obj { age: 25 }&#xff0…

设备太分散?如何一站式管理边缘 OS、K8s 和应用?

作者简介 张志龙&#xff0c;SUSE 大中华区资深解决方案架构师&#xff0c;CNCF 官方认证的 CKA&CKAD 工程师&#xff0c;深耕以 Kubernetes 为代表的云原生领域&#xff0c;具备丰富的架构设计、业务容器化改造和项目落地实践经验。 据 Gartner 预测&#xff0c;到 2025 年…

【GlobalMapper精品教程】053:打开dbf文件并生成有坐标系的shp数据

本文讲解在globalmapper汇总打开dbf文件并生成有坐标系的shp数据。 文章目录一、dbf文件解读二、打开dbf文件二、另存为shp文件一、dbf文件解读 我们可以通过Excel或FME等多种软件查看dbf的结构&#xff0c;字段有&#xff1a;Name&#xff0c;kind&#xff0c;Lat&#xff0c…

事理知识图谱

事理知识图谱能够有力第建模各类事件之间的演化关联关系为事理逻辑推理提供更好的数据基础。 事理图谱定义 事理知识图谱可以将文本中对事件以及事件之间的关系抽取并抽象出来&#xff0c;构建成一个有向图形式的事理知识库。在结构上&#xff0c;事理知识图谱是一个有向有环…

SparkSQL

第1章 SparkSQL 概述1.1 SparkSQL 是什么Spark SQL 是 Spark 用于结构化数据(structured data)处理的 Spark 模块。1.2 Hive and SparkSQLSparkSQL 的前身是 Shark&#xff0c;给熟悉 RDBMS 但又不理解 MapReduce 的技术人员提供快速上手的工具。Hive 是早期唯一运行在 Hadoop …

vue项目中引入字体包

问题&#xff1a; 项目开发过程中&#xff0c;因UI的显示要求&#xff0c;需要引入一些字体&#xff0c;那如何引入外部字体呢&#xff1f;很简单&#xff0c;只需要以下3步 一 下载对应的字体包文件&#xff0c;放置到我们的项目中 ​ 比如我需要PingFangSC的系列字体&#…

交叉编译 cJSON

交叉编译 cJSON 概述 JSON 是一种轻量级数据交换格式。它可以表示数据、字符串、有序的值序列以及名称/值对的集合。 cJSON 是 ANSI C 中超轻量级的 JSON 解析器。cJSON 旨在成为您可以完成任务的最简单的解析器。它是一个 C 文件和一个头文件。作为一个库&#xff0c;cJSON…

VR全景+汽车,打造汽车销售新模式

在国内汽车市场竞争越来越激烈的背景下&#xff0c;传统汽车、混动汽车、新能源汽车等各类汽车市场正在不断壮大&#xff0c;汽车行业企业必须抓住机遇、迎接挑战&#xff0c;而营销引流则是关键步骤之一。未来&#xff0c;汽车行业的营销方式将更加高效数字化&#xff0c;采用…

Python学习-----lambda式匿名函数

目录 前言&#xff1a; 1.什么是lambda函数 2.使用示例 &#xff08;1&#xff09;示例1&#xff1a;与def对比 &#xff08;2&#xff09;示例2&#xff1a;与三目运算符 &#xff08;3&#xff09;示例3&#xff1a;lambda作为参数传入其他函数 &#xff08;4&#xff…