Linux学习:进程(3)与 环境变量

目录

  • 1. 进程的优先级
    • 1.1 什么是进程的优先级
    • 1.2 优先级的具体表示与查看方式
  • 2. 进程的切换与调度
    • 2.1 切换
    • 2.2 调度
  • 3. 环境变量
    • 3.1 main参数/命令行参数
    • 3.2 什么是环境变量
    • 3.3 环境变量的使用与特性
    • 3.5 本地变量与环境变量的脚本配置文件

1. 进程的优先级

  1. 在计算机运行的过程中,有着许许多多的需要被执行的进程,而就绪状态的进程被加载到内存中的运行队列上。那么,它们之间的先后是如何区分的,它们是照申请先后的顺序排列而后执行吗?接下来,让我们对进程的新属性,进程的优先级来进行学习与了解。

1.1 什么是进程的优先级

  1. 在现实生活中,各种事物的优先级代表着这些事物所要被执行的先后顺序。而在计算机中对于进程来说,也是如此,进程的优先级决定了其被CPU执行的先后顺序。
  2. 当我们去谈论优先级的概念时,就代表有了需要我们去讨论优先级的前提与场景,进程的优先级决定着进程被CPU的执行顺序。
  3. 而当我们提及到进程的优先级时,就一定代表着CPU不能够第一时间内处理所有需要被进行的进程,或者可以说CPU的资源无法满足支持可以第一时间处理每个进程,所以,此时就需要将各个进程进行排队等待。
  4. 内存中需要被执行的进程各种各样,我们应该怎么将它们进行排队,并且需要保证排队的方式足够合理与高效,可以支持操作系统与各个进程的正常运行。

1.2 优先级的具体表示与查看方式

  1. 优先级也属于进程PCB属性中的一个,我们使用指令ps -la [进程号],可以查看到指定进程的优先级等相关信息。(PRI:priority)

在这里插入图片描述

  1. 进程的优先级表示,PCB中以int类型的变量来表示进程的优先级,其可被修改的数据范围为 [60,99],一共40个数,数值越小优先级越高,数值越大优先级越低。
  2. Linux下我们创建的每个进程的优先级默认为80,每个进程的优先级是可以被我们手动更改的,进程优先级计算判定由两部分组成old PRI + NI(nice)
  3. 我们无法直接修改PRI,需要通过修改NI从而达到间接修改PRI的效果,修改指令为renice [n] [进程号],n的取值范围为 [-20, 19],每次计算的old PRI都是从默认PRI即80开始计算的,而每次对NI的写入都是覆盖式写入。

在这里插入图片描述

  1. 当使用renice指令调整NI的范围超过[-20, 19]时,renice只会取极值不会超过NI的限制范围。

补充:为什么要对能够修改的优先级划定范围

  1. 当进程优先级的优先级可以被随意修改时,可能会因为认为的操作出现大量的高优先级的进程,这些进程会大量占用CPU的资源,甚至可能会导致原本的进程因此无法被CPU执行,导致这些进程及其卡顿甚至不能够被运行。
  2. 这些因为高优先级泛滥问题而不能够被正常执行的进程,我们称之为饥饿进程

2. 进程的切换与调度

2.1 切换

  1. CPU具体是如何处理一个个进程的,每一个进程都是在CPU上一直被执行,直到彻底执行完毕吗?
  2. 事实并给如此,Linux操作系统中进程的执行方式是以时间片进行切换,每个进程都以时间片(1ms)为单位进行轮转执行。
  1. 进程相关概念补充:
    <1> 竞争性:进程会因为优先级的不同区分先后顺序
    <2> 独立性:各个进程之间不会相互干扰,独享各种资源
    <3> 并行:计算机中有多个CPU,各个进程被分散在不同CPU上同时执行
    <4> 并发:多个进程被一个CPU通过高频进程切换得方式执行,同时得以推进
  2. 多核:CPU有一个控制器,同时拥有多个运算器
  1. CPU存在着大量的寄存器,不同种类的寄存器担任着不同的职能:
    <1> eax/ebx/ecx/edx,通用寄存器:临时性的数据保存
    <2> eds/ecs/fg/gs,段寄存器:衡量区域调用数据的区域
    <3> eip/cr0-cr4,PC指针:记录标识程序执行到的进度与位置
    <4> 程序状态字
    <5> 浮点数存储器
    <6> ebp/esp(小盒子),函数栈帧开辟相关
  2. 根据前面的了解,我们直到进程是以时间片为单位在CPU上执行的,而进程被执行时会携带着大量的自身数据,这些数据是需要交给CPU进行处理计算的,CPU获取与存储这些数据的方式就是将它们拷贝至自身的寄存器中。(寄存器不等于寄存器内容,一套寄存器可以有多套寄存器内容)
  3. 进程被切换走,中断执行的步骤:
    <1> 剥离寄存器中的核心数据数据
    <2> 将核心数据全部带走,保存至进程的PCB中,记录执行进行执行到的位置,即,保护进程的硬件上下文数据(CPU内部所有的临时数据)
  4. 进程二次切换回来,继续执行的步骤:
    <1> 恢复上下文,覆盖是写入上下文数据
    <2> 从上次执行到的位置继续执行

在这里插入图片描述

2.2 调度

  1. 操作系统按照一定的方式去执行运行队列上的各种进程,这就被称为进程的调度,不同的操作系统对于进程有着不同的调度算法。
  2. 根据操作系统应用场景的不同,按照进程调度算法的偏向不同可以分为两类:
    <1> 分时优先级:操作系统会公平的执行每个进程
    <2> 时时优先级:操作系统对于用户的请求,发送的进程会进行优先处理,高响应(车载系统)
  1. Linux操作系统O(1)调度算法:

在这里插入图片描述

  1. O(1)调度算法操作步骤 与 变量解释:
    <1> struct task_struct* queue[140]:PCB指针数组,进程的可修改优先级范围为40,此数组开放[100, 139]范围的40个下标用来存储不同优先级队列的指针
    <2> int bitmap[5]:int类型数组,其容量大小为5,有40个bit位,每一位都标识着一个优先级运行队列中是否有进程,二进制位为1代表有,0代表没有。通过这种方式,可以位运算的方法快速检测并找到需要被执行有进程的优先级队列
    <3> int nr_active:一个整形变量,标识bitmap中8组优先级队列是否仍有进程剩余,若没有值为0,若有值为非0
    <4> 运行队列中存在着两个相同的结构,分别用来标识活跃队列与过期队列,CPU只会执行活跃队列中的进程,而新进的进程只会添加至过期队列中。
    <5> 通过活跃队列与过期队列的方式,O(1)调度算法很好的规避的优先级队列的进程饥饿问题
    <6> struct q* active:执行活跃队列的指针
    <7> struct q* expried:指向过期队列的指针
    <8> 当活跃队列中的进程执行完毕,active与expried指针就会进行值交换,这样就达到了运行队列切换的效果,又因为只是指针的交换,消耗极小,效率很高

3. 环境变量

3.1 main参数/命令行参数

  1. 从初始接触编程开始我们就识得了main函数,在使用时从来没有给main函数传递过参数,可是,main函数真的没有参数吗
  2. main函数其实存在着三个可以添加的隐藏参数,接下来就让我们来进行对它们的学习
int main(int argc, char* argv[], char* env[])
{return 0;
}
  1. 命令行参数argvargv
    <1> argv:字符串类型的数组,执行可执行程序时,从命令行中以空格为间隔获取字符串
    <2> argv:argv字符串数组的元素个数
int main(int argc, char* argv[])
{int i = 0;for(i = 0; i < argc; i++){printf("%s\n", argv[i]);}return 0;
}

在这里插入图片描述

  1. 我们在前面的学习中已经了解到,操作系统中的一个个指令其实都是可执行程序,而各种指令附带不同的参数选项就有不同的效果,其底层的实现就是利用了命令行参数实现的。类似操作,如下
 int main(int argc, char* argv[])                                                                                                                                                       
{if(argc != 2){printf("waring Usage:\n\t./process [a~c]\n\n");}else if(strcmp(argv[1], "-a") == 0){printf("-a usage\n");}else if(strcmp(argv[1], "-b")== 0 ){printf("-b usage\n");}else if(strcmp(argv[1], "-c") == 0){printf("-cx usage\n");}else{printf("no usage\n");}return 0;}

在这里插入图片描述

3.2 什么是环境变量

  1. 在编程语言中的变量是我们于内存中开辟的一块空间,我们赋予这块空间名称并以此调用这块空间进行各种数据的存储与运算,变量在运行期间也可以开辟。
  2. 环境变量也是变量,同样与编程语言中变量的属性相同,不同的只是环境变量是操作系统从内存中申请,用来存放一些必要的信息资源,系统内置具有特殊用途的变量。
  3. 系统中的环境变量有许多,环境变量的命名方式通常都为大写英文字母前加特殊符号:$环境变量名,我们可以通过指令:echo [环境变量]来查看对应环境内的具体内容。

在这里插入图片描述

  1. 下面罗列几个常见的环境变量:
    <1> $PATH:存放常用资源路径的环境变量
    <2> $USER:存放当前用户名的环境变量
    <3> $PWD:存放当前所处目录路径的环境变量
    <4> $HOME:存放当前用户家目录的环境变量
  1. 我们在前面的学习中了解到,可执行程序要想运行必须要给出可执行程序的绝对或相对路径,让操作系统可以找到对应可执行程序并执行。
  2. 可是,系统中的一些自带指令为什么调用时可以不加路径声明呢,这是因为系统每次启动时bash都会在$PATH环境变量中会默认添加入,系统自带指令的所在路径,这样我们在使用这些指令时系统可以直接从环境变量中拿到自己需要的资源信息。

在这里插入图片描述

  1. 我们若想让自己编写的可执行程序像系统自带指令一样使用,有两种方法:
    <1> 像操作系统登录时每次都会检索并以以此生成环境变量的路径里添加我们的可执行程序(不推荐,开发不完备可能会污染其他文件)
    <2> 向环境变量$PATH中临时添加我们可执行程序所在的路径,退出销毁,指令如下:
PAHT=[需添加路径]:$PATH
//:$PATH不可省,否则会将原有的内容全部覆盖

在这里插入图片描述

3.3 环境变量的使用与特性

  1. main函数的第三个命令行参数char* env[],是一个字符串数组以NULL结尾,其中存储内容为父进程传递给main函数所在可执行程序的环境变量。
int main(int argc, char* argv[], char* env[])
{int i = 0;for(i = 0; env; i++){printf("%s\n", env[i]);}return 0;
}

在这里插入图片描述

  1. 环境变量为全局属性,子进程可以继承父进程的环境变量,bash命令行解释器是我们所创建进程的父进程。
  2. 定义环境变量的方式:export [环境变量名]=[赋值]

在这里插入图片描述

  1. 子进程除开通过传递env环境变量参数列表的方式一次性获取父进程所有环境变量,我们还可以通过C语言库中函数getenv获得指定的环境变量。(stdlib.h头文件中)
//身份识别
int main()
{if(strcmp(getenv("USER"), "zyc") == 0){printf("this is a limited core process\n");}return 0;
}
  1. C语言库中存在着一个第三方变量environ,此变量的是一个二级指针数组,其中以字符串指针的形式存放着bash进程中所有的环境变量。
int main()
{//做符号声明extern char** environ;int i = 0;for( i = 0; environ[i]; i++){printf("%s\n", environ[i]);}return 0;
}

3.5 本地变量与环境变量的脚本配置文件

  1. 环境变量为bash定义,适用于不同应用环境具有特殊用途的信息。而系统中拥有的变量种类不止一种,还有很多其他种类。
  2. 本地变量:一种在当前bash进程内定义,不能被子进程继承只在bash内部有效的变量
  3. 定义本地变量的方式:[变量名]=[赋值],查看本地变量:echo [$本地变量]
  4. <1> 指令:set(查看所有变量,包括环境变量与本地变量)
    <2> 指令:unset(从上下文信息中移除变量)
  1. 经过前面的学习我们已经知道,环境变量是通过bash进程定义出来,我们此退出后重新登录Xshell后,之前定义的环境变量就会消失。
  2. 可是为什么bash自带的环境变量不会消失呢,其实这些环境变量并不是不会消失,而是存储在服务器磁盘中脚本与配置文件中,每次我们登录Xshell重新启动bash进程,都会导入脚本。
  3. 我们若想要让自己定义的环境变量等也可以登录加载,就可以通过在配置文件中添加定义的方式来实现。
  4. 每个用户的配置文件都不同,它们都处于当前用户的家目录下,文件名为.bash_profile,此文件又从bashrc中导入内容。
  5. 在配置文件.bash_profile中添加提示语,可以登陆时提示。

在这里插入图片描述
示例:
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

【JavaScript】数组 ② ( JavaScript 数组索引 | JavaScript 遍历数组 | 使用 for 循环遍历数组 )

文章目录 一、JavaScript 数组索引1、数组索引2、数组索引 - 代码示例 二、JavaScript 遍历数组1、使用 for 循环遍历数组2、使用 for 循环遍历数组 - 代码示例 一、JavaScript 数组索引 1、数组索引 在 JavaScript 中 , 数组 的 " 索引 " 又称为 " 下标 "…

电脑突然死机怎么办?

死机是电脑常见的故障问题&#xff0c;尤其是对于老式电脑来说&#xff0c;一言不合电脑画面就静止了&#xff0c;最后只能强制关机重启。那么你一定想知道是什么原因造成的吧&#xff0c;一般散热不良最容易让电脑死机&#xff0c;还有系统故障&#xff0c;比如不小心误删了系…

React 应用实现监控可观测性最佳实践

前言 React 是一个用于构建用户界面的 JavaScript 框架。它采用了虚拟 DOM 和 JSX&#xff0c;提供了一种声明式的、组件化的编程模型&#xff0c;以便更高效地构建用户界面。无论是简单还是复杂的界面&#xff0c;React 都可以胜任。 YApi 是使用 React 编写的高效、易用、功…

2.人机交互-图形化界面的小故事

文章目录 一、图形化界面的小故事二、什么是cmd&#xff1f; 计算机在刚开始出现的时候&#xff0c;因为占地广、造价高、耗电多&#xff0c;一般都是给军队或者政府使用的&#xff0c;而并不是给个人使用的。然后随着计算机不断地发展&#xff0c;体积越来越小&#xff0c;出现…

【计算机网络篇】数据链路层(4.1)可靠传输的相关概念

文章目录 &#x1f354;可靠传输的相关概念⭐分组丢失⭐分组失序⭐分组重复 &#x1f95a;注意 &#x1f354;可靠传输的相关概念 使用差错检测技术&#xff08;例如循环冗余校验CRC&#xff09;&#xff0c;接收方的数据链路层就可以检测出帧在传输过程中是否产生了误码&…

B2902A是德科技B2902A精密型电源

181/2461/8938产品概述&#xff1a; Agilent B2902A 精密源/测量单元 (SMU) 是一款 2 通道、紧凑且经济高效的台式 SMU&#xff0c;能够源和测量电压和电流。它用途广泛&#xff0c;可以轻松、高精度地执行 I/V&#xff08;电流与电压&#xff09;测量。4 象限源和测量功能的集…

linux 内存介绍

大致共有四类&#xff1a;VSS、RSS、PSS、USS &#xff0c;通常情况下&#xff0c;VSS > RSS > PSS > USS 1.VSS(Virtual Set Size)虚拟耗用内存&#xff08;包含共享库占用的内存&#xff09; VSS表示一个进程可访问的全部内存地址空间的大小。这个大小包括了进程已…

单例模式如何保证实例的唯一性

前言 什么是单例模式 指一个类只有一个实例&#xff0c;且该类能自行创建这个实例的一种创建型设计模式。使用目的&#xff1a;确保在整个系统中只能出现类的一个实例&#xff0c;即一个类只有一个对象。对于频繁使用的对象&#xff0c;“忽略”创建时的开销。特点&#xff1a…

Netty对Channel事件的处理以及空轮询Bug的解决

继续上一篇Netty文章&#xff0c;这篇文章主要分析Netty对Channel事件的处理以及空轮询Bug的解决 当Netty中采用循环处理事件和提交的任务时 由于此时我在客户端建立连接&#xff0c;此时服务端没有提交任何任务 此时select方法让Selector进入无休止的阻塞等待 此时selectCnt进…

骗子查询系统源码

源码简介 小权云黑管理系统 V1.0 功能如下&#xff1a; 1.添加骗子&#xff0c;查询骗子 2.可添加团队后台方便审核用 3.在线反馈留言系统 4.前台提交骗子&#xff0c;后台需要审核才能过 5.后台使用光年UI界面 6.新增导航列表&#xff0c;可给网站添加导航友链 7.可添加云黑类…

Flink系列之:Flink SQL Gateway

Flink系列之&#xff1a;Flink SQL Gateway 一、Flink SQL Gateway二、部署三、启动SQL Gateway四、运行 SQL 查询五、SQL 网关启动选项六、SQL网关配置七、支持的端点 一、Flink SQL Gateway SQL 网关是一项允许多个客户端从远程并发执行 SQL 的服务。它提供了一种简单的方法…

Flink集群主节点JobManager启动分析

1.概述 JobManager 是 Flink 集群的主节点&#xff0c;它包含三大重要的组件&#xff1a; ResourceManager Flink集群的资源管理器&#xff0c;负责slot的管理和申请工作。 Dispatcher 负责接收客户端提交的 JobGraph&#xff0c;随后启动一个Jobmanager&#xff0c;类似 Yarn…

C/C++语言学习路线: 嵌入式开发、底层软件、操作系统方向(持续更新)

初级&#xff1a;用好手上的锤子 1 【感性】认识 C 系编程语言开发调试过程 1.1 视频教程点到为止 1.2 炫技视频看看就行 1.3 编程游戏不玩也罢 有些游戏的主题任务就是编程&#xff0c;游戏和实际应用环境有一定差异&#xff08;工具、操作流程&#xff09;&#xff0c;在…

C# OpenCv Haar、LBP 人脸检测

目录 效果 代码 下载 效果 代码 using OpenCvSharp;namespace OPenCVDemo {class Program{static void Main(string[] args){// Load the cascadesvar haarCascade new CascadeClassifier("haarcascade_frontalface_default.xml");var lbpCascade new Casca…

1学习使用axios

一、axios介绍&#xff1a; axios 是一个基于 Promise 的 HTTP 客户端&#xff0c;用于浏览器和 Node.js。它提供了一种简单的方法来发送 HTTP 请求&#xff0c;并且具有很多实用的功能&#xff0c;使得网络请求变得更加方便和可靠。 以下是 axios 的一些主要特点和功能&…

【笔记】RDD算子操作(Spark基础知识)

持续更新中&#xff01;&#xff01;&#xff01; 目录 一、RDD的创建 1.从本地创建 &#xff08;1&#xff09;本地文件 &#xff08;2&#xff09;hdfs文件&#xff08;先提前创建目录并上传文件&#xff09; 2.从集合创建&#xff08;通过并行集合&#xff08;列表&am…

学点Java_Day12_JDBC

1 JDBC 面向接口编程 在JDBC里面Java这个公司只是提供了一套接口Connection、Statement、ResultSet&#xff0c;每个数据库厂商实现了这套接口&#xff0c;例如MySql公司实现了&#xff1a;MySql驱动程序里面实现了这套接口&#xff0c;Java程序员只要调用实现了这些方法就可以…

如何调试Clang源码

下载编译Clang 这个就直接去LLVM官网下载&#xff0c;然后编译好Clang就行&#xff0c;注意得debug模式&#xff0c;保存符号信息。 调试Clang 可以直接通过命令行来调试 #进入调试环境&#xff0c;这里的clang得是刚刚编译好的 lldb ./clang # r是运行&#xff0c;后面是正…

电脑关机速度很慢怎么解决?

给电脑关机&#xff0c;总是要很久才完全关闭。这是因为计算机运行了太长时间&#xff0c;并且打开的程序太多&#xff0c;则关闭时间超过十秒钟&#xff0c;这是正常的现象。还有就是计算机升级或补丁程序更新也将导致计算机缓慢关闭。此时&#xff0c;建议耐心等待关闭完成。…

离心式风机运行效率测算

1.总压静压动压&#xff1b; 2.动压0.5空气体密度风速2&#xff1b; 风机所需功率P&#xff08;KW&#xff09;&#xff1a;PQp/&#xff08;36001000η0η1&#xff09; Q—风量&#xff0c;m3/h&#xff1b; p—风机的全风压&#xff0c;Pa&#xff1b; η0—风机的内效率&a…