学习系统编程No.4【环境变量】

news2025/7/11 3:21:11

引言:

北京时间:2023/2/20/22:15,昨天晚上,看了一晚上的cs:go,主要原因是因为我的好舍友,叫我开箱子,然后就不可言语,看了一晚上的开箱子和精彩剪辑,不过这个游戏确实是颠覆了我对游戏的认知,游戏里的装备居然是可以卖钱的,我发现这个游戏机制非常好,但是这个游戏对新手不太友好,不然这个游戏还是挺快乐的,并且该游戏里的装备也颠覆了我对钱的认知,……,今天就让我们来学习一下孤儿进程、环境变量、优先级和地址空间相关的知识。
在这里插入图片描述

什么是孤儿进程

在上一篇博客中,我们已经学习了什么是僵尸进程,我相信大家都知道,我们是通过把某一个子进程使用kill -9 PID 的方式,来把该进程给杀掉,之后才导致一个进程从运行状态(R)或者睡眠状态(S),变成了僵尸状态(Z),所以可以想象如果此时我们不是把某个子进程杀掉,而是把某个子进程的父进程杀掉,此时是什么情况呢?如下图:

在这里插入图片描述
从上图的代码中我们可以看出,我们使用fork()函数创建了两个一样的进程,此时这两个进程可以同时执行while循环语句,并且判断条件互不干扰,重点:此时还可以看出,下面的循环,也就是父进程的循环不是死循环,而是只循环10次,10次之后,该循环就会停止,也就意味着上面循环进程的父进程停止了,此时该子进程就没有了相应的父进程,但又可以发现,当父进程停止之后,此时该子进程的父进程从原来的22024变成了1,这是为什么呢?并且从右图可以看到,此时当父进程停止之后,父进程直接消失了,按照之前学习的知识,不是说进程停止之后会先变成僵尸状态吗?这又是为什么呢?
原因就是:本质上,一个子进程停止之后,它的父进程就会把它给回收,并且由于bash是所有子进程的父进程,所以此时当该进程的父进程停止之后,该父进程就会直接被bash进程给回收,所以我们看不到该进程变成僵尸状态,并且当该进程的父进程如果先停止,那么此时该进程就会直接默认的被1号进程(操作系统)给领养,使其拥有一个新的父进程,所以此时该子进程就是我们所说的孤儿进程
为什么会有孤儿进程的概念
从逆向的角度思考,此时如果该进程没有新的父进程,不是孤儿进程,那么此时会导致什么问题呢?首先明白,只有父进程可以给子进程收尸,其次明白,不收拾会怎样,得出结论:如果一个子进程没有父进程就会导致无法收尸,就会导致该子进程无法管理,使该子进程一直在我们的内存中占空间,最终导致:内存泄露问题,程序崩溃。

并且此时杀掉进程有两种方式,一种是杀掉该进程的PID(kill -9 PID),一种是直接杀掉该目标进程(killall 目标进程),所以你想让那个进程当孤儿进程你就杀掉谁的父进程,哈哈哈哈!

什么是环境变量

搞定了上述的孤儿进程的知识之后,进程状态相关的知识,我们就搞定的差不多了,像进程中比较特殊的僵尸进程和孤儿进程我已经通过Linux下的代码进程看到了相应的场景,当然进程状态中比较特殊的还有守护进程和精灵进程之类,这些我们目前先不做了解,接下来就让我们学习一下什么是环境变量吧!
首先我们先从一个问题出发,就是当我们写法代码,编译之后,想要运行,为什么一定要加 (./) 符号呢?为什么像Linux中的基本指令ls、cd、rm、cp、mv等,不要呢?如图:
在这里插入图片描述
只有输入了 (./) 符号才可以执行该程序,(./) 到底是什么意思呢?首先要明白一点,执行一条命令的前提是找到这条命令,所以此时明白 (./) 的意思就是在本地寻找这个文件,如果本地有该文件就执行,否则就报找不到该指令,同理,在我们的Linux系统中也存在一个叫 PATH 的环境变量,在我们输入了ls、cd、rm、cp、mv这些基本指令的时候,系统会自己去PATH 的环境变量中寻找这些指令的,如果环境变量中存在则执行,不存在则报找不到该指令。
所以上述问题的答案就是: 我们生成的可执行文件,并不在系统的PATH 环境变量中,想要执行该文件,就要我们自己指明该文件对应的路径 (./)

搞懂了这些,相信我们就明白,我们是可以自己找到PATH环境变量,然后把自己的可执行程序给加入到PATH环境变量中的,然后在执行该程序的时候,就不需要让我们自己指定路径,而是让系统直接去PATH 环境变量中找该程序,使我们直接输入程序名就可以,不需要指明(./)
如图
在这里插入图片描述
上图表示的就是,使用 export 指令,向PATH中写入程序路径,但是要注意: 此时不可以直接向PATH中写入,而是要在 $PATH的后面进行插入,不然会把PATH中原有的路径给覆盖掉,导致出现问题(不过重启软件之后可以恢复),所以此时这种行为就相当于是在Linux系统中安装了一个软件!所以无论是Windows还是Linux,只要是安装软件,本质上就是在把该软件对应的可执行文件拷贝到我们电脑相应的路径下

查看环境变量

输入 env指令 ,查看Linux系统中的环境变量
在这里插入图片描述
在高级系统设置中查看Windows系统中的环境变量

上述有非常多的环境变量,每一个都有它们对应的作用,并且这些作用是非常重要的,但是目前对我们来说最重要的就是上述提到的PATH(搜索环境变量)

查看main函数中的环境变量表

int main(int argc,char* argv[],char* envp[])
对于以前学习C语言来说,我们是不需要对main进行传参,也没有函数可以调用main函数进行传参,但本质上,main函数是可以进行传参的,并且此时由于没人可以调用main函数,所以此时参数的数据就是通过命令行解释器获得,就是Linux中的bash获得,并且此时main函数是可以传三个参数的,其中有一个就是指向环境变量表的一个字符指针数组

如图所示:
在这里插入图片描述
所以此时main函数中的 char* envp[] 指针数组,就是代表我们的环境变量表;

在这里插入图片描述
并且此时根据图中的代码,可以通过循环的方式,直接将该指针数组中的指针所指向的数据进行一一打印,所以如上图,我们就得到了环境变量表中的所有环境变量。

并且如果不使用main函数中的参数 char* envp[] 指针数组,此时也是可以获得环境变量,方法就是使用函数 environ 或者 getenv ,如下代码:
在这里插入图片描述
使用该代码,也可以很好的把环境变量表中的所有环境变量给打印出来,跟上图是一样的,此时不多加插入了, 注意:此时因为我们要访问的是一个指针数组,所以此时需要使用二级指针,所以要写成 char** environ,并且加上extern,表示从外部引用,这样才可以很好的访问环境变量表。

在这里插入图片描述
此时我们就可以把环境变量表中的USER环境变量中的数据给打印出来了,该函数的好处就是可以一个一个的获得我们想要的环境变量;重点: 所以无论是我们的user指令,还是pwd指令,还是cd等指令,其实本质上都是通过getenv函数来实现其特定的功能的,比如上述我们就自己实现了一个可以打印user的指令。
并且如果我们想要自己实现pwd和cd等指令,只需要把上图代码中的user换成pwd或者cd就行了,通过getenv函数我们可以直接拿到任何的环境变量,实现任何的环境指令。

使用环境变量实现权限问题

如下代码,充分表明了环境变量对于权限方面的使用方法,可以通过环境变量中的USER,来控制用户权限。
在这里插入图片描述

总:环境变量本质就是一个内存级的一张表(内存中的某块地址),这张表由用户在登录系统的时候,系统自动进行给特定用户形成属于自己的环境变量表,并且每一个环境变量都有自己的特定使用场景。

系统如何配置环境变量

通过上述总结可以知道,环境变量是系统自动帮我们配置的,那么就有一个问题,系统是如何进行环境变量的配置呢? 此时就涉及到了两个Linux系统中的两个文件,一个是 .bash_profile ,一个是 .bashrc 如图:

在这里插入图片描述
在这里插入图片描述
所以在我们登录的时候,系统就会自动帮我们加载上述两个文件, .bash_profile.bashrc 中的配置文件,将环境变量给配置完成,具体原理:就是将上述两个配置文件中的默认程序加载到命令行解释器(bash)中。

浅谈环境变量的继承

搞定了上述加载环境变量相关知识,此时我们来看看环境变量的另一方面的知识,环境变量的继承,在理解环境变量的继承之前,我们写复习一下以前的知识:父进程是如何创建子进程的
如图:
在这里插入图片描述
我们可以看到,父进程在创建子进程的时候,会将自己的大部分属性数据拷贝给子进程,所以明白了这个道理,我们就可以谈谈环境变量的继承问题了;谈继承问题的第一个前提:明白环境变量本质上是在命令行解释器(shell、bash)进程中,由命令行解释器(shell、bash)进程控制的, 所以当我们的shell进程在创建子进程的时候,就会像上图一样,将自己属性中的环境变量给拷贝给子进程,所以这就是环境变量的继承现象,并且深入理解,可以发现,当我们在shell中创建一个环境变量时,该环境变量并不会被子进程继承,只有当该环境变量被export指令写入到了环境变量表中时,子进程才可以继承,所以得出结论:shell的本地变量只在shell内部有效,不可以被子进程继承(只有当使用了export把shell的本地变量导入到环境变量表后,子进程才可以继承),进一步说明,环境变量表是在shell进程中被控制。

source(.) 让配置文件立即生效指令

什么是命令行参数

从main函数中看命令函参数:int main(int argc,char* argv[])
在这里插入图片描述
所以此时main函数中的int argc参数代表的就是各种的参数选项,并且第一个下标永远存放的是该可执行程序(myproc).

并且此时char* argv[]表示的就是:如下图
在这里插入图片描述

int argc;中的参数选项提供存储空间,所以main函数中的两个命令函参数就是用来提供参数选项和存储参数选项的。
注意:该参数选项表是由Linux中的命令行解释器bash生成的,并且目的就是提供给子进程中的环境变量使用。

总:int argc代表的就是命令行参数对应的个数,int argv[]代表的就是各个参数对应的起始地址。

命令行参数有什么用呢?

我相信大家都很好奇,命令行参数到底有什么用,因为平常我们使用C语言写代码的时候,main函数中的参数永远是为空的,表明命令行参数对于我们写C语言代码是起不到作用的,本质原因:也是因为我们无法去调用main函数,但是当我们呢在Linux系统中时,因为有了命令行解释器(bash),并且因为bash是所有进程的父进程,所以此时命令行解释器是可以通过控制子进程的方式去控制main函数,给main中的形参提供实参的,所以我们把main函数中的参数就叫做命令行参数,那么命令行解释器(bash)为什么要给main函数(子进程)提供参数呢?或者可以说,命令行解释器给main函数提供参数有什么用呢?接下来,我们就通过一个代码来具体看一看,命令行参数给main函数传参的用处(用处巨大):
在这里插入图片描述

通过上图,可以看出,我们可以根据不同的命令行参数中的不同的选项,让我们的同一个程序,执行不同的不能(本质就是ifelse if 的使用),所以例如我们以前使用的(ls)指令,就是通过命令行参数的形式,将自己不同的选项传递给相应的程序使用,然后该程序在其内部对相应选项进行判断(else if),这样就可以让同一个指令(软件)执行不同的功能了,如:(ls -a ,ls -l,ls -t,ls -b)等等!

进程的优先级问题

通过以前知识的学习,我们可以很清楚的知道,在系统当中,所有的资源都是有限的,导致排队是必须的,有排队就会涉及优先级的问题:所以让我们看一下什么是优先级或者说系统内部是怎样排队的,进程的优先级(PRI),也就是被CPU执行的先后顺序,该值越小,进程的优先级越高,优先级的修正数值(NI)表示进程可被执行的优先级的修正数值,PRI值越小越快被执行,加入NI之后,就会变成 PRI(new) = PRI(old)+NI所以NI可以决定PRI,调整NI就是在调整进程的优先级,注意:NI表示的只是进程的修正数据,不是进程优先级,所以本质上,我们是通过修改NI的值来修改进程的优先级的,如下图:
在这里插入图片描述
可以发现,输入ps -al指令,我们就可以看见刚刚创建的进程的PRI和NI数据,并且此时如果输入top指令,我们可以看到,如下图的场景:
在这里插入图片描述
所以此时我们就可以通过这个场景来修改我们进程的优先级(PRI),当然本质是通过UI来修改;输入r,可以看到一个命令行,此时就可以进行优先级的设置,(通过PID来设置),输入PID之后,你就可以看到如下图的场景:在这里插入图片描述
此时就可以输入你想设置的UI值了(-20~19),例如:此时我输入了一个10,此时我的UI值就变成了10,进程的优先级就变成了90,如下图:
在这里插入图片描述
充分表明此时我们是可以通过UI来调整我们的进程优先级(PRI),并且PID的范围也必须符合UI的范围(注意:想要通过UI修改PRI,此时的PRI每一次都是从80开始,修改之后的PRI不会叠加,永远从80开始

进程的特性:

搞定了上述的进程的优先级的问题,此时我们可以通过进程的优先级和以前学习的有关进程的相关的知识,得出一些有关进程的特性:

进程具有竞争性、独立性、并行、并发等特性
竞争性:系统进程数目众多,而CPU资源有限,所以进程之间是具有竞争属性的,为了提高效率,更合理的使用资源,就有了进程优先级的概念
独立性:多进程运行,需要独享各种资源、多进程运行期间互不干扰
并行:多个进程在多个CPU下分别,同时进行运行
并发:多个进程在一个CPU下采用进程切换的方式,在这一时间之内,让多个进程都得以推进

在这里插入图片描述

总结: 环境变量和我们的系统是密不可分的,和我们的进程是息息相关的。

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

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

相关文章

携手同心,三阳开泰:读懂2023华为中国政企合作伙伴政策

导语: 《周易》中,把连在一起的爻称为阳爻,乾下坤上,三个阳爻组合在一起,就是泰卦。这也就是“三阳开泰”这个成语的由来,其中“泰”字,代表着冬去春来,有吉亨之象,既象征…

烧录OpenStLinux到Stm32mp157上

STM32CubeProgrammer是ST官方专门为Corex-A stm32mp157这样高端系列开发的烧录工具你需要到ST官方网站上下载STM32CubeProgrammerST官方下载地址:https://www.st.com/zh/development-tools/stm32cubeprog.html注意下载的系统版本,下载完成之后默认安装就…

必备 | Elasticsearch 8.X 最少必要知识视频(全)

1、你使用 Elasticsearch 8.X 了吗?Elastic Stack 数据平台由Logstash、Beats、ElasticSearch和Kibana四大核心产品组成,在数据摄取、存储计算分析及数据可视化方面有着无可比拟的优势。在存储、计算和分析方面,ElasticSearch允许执行和合并多…

40、基于51单片机收音机 LCD1602显示系统设计

摘要 本文在具体分析了STC89C52单片机的技术特点与数字FM收音机的基础上,提出了采用单片机控制收音机实现数字调频的方法,并给出了具体的软硬件设计。该系统利主要由STC89C52单片机、液晶显示器、按键、调频收音模块TEA5767、功放LM386组成。实际运行时…

「TCG 规范解读」第12章 TPM工作组 TCG身份验证研讨

可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…

XC7K70T-1FBG676C应用XC7K70T-L2FBG484E Kintex-7, FPGA 规格参数

概述Kintex-7 FPGA为快速增长应用和无线通信提供最优性价比和低功耗。Kintex-7 FPGA允许设计人员构建卓越带宽和12位数字可编程模拟,同时满足成本和功耗要求。144GMACS数字信号处理器 (DSP) 的独特功耗使得多功能Kintex-7器件成为便携式超声波设备和下一代通信等应用…

5. 阿里巴巴程序员开发手册黄山版

学习的动力不止于此: 最近阅读了刘典武大神推荐的阿里巴巴Java开发手册泰山版。里面的很多规范不仅仅适用于Java。非常值得我们一起学习。 于是,我找了最新的版本–黄山版。 正所谓,五岳归来不看山,黄山归来不看岳。最新版本—…

06_MySQL多表查询

多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。前提条件:这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段,这个关联字段可能建立了外键,也…

Crafting interpreters 中文翻译(全),持续修正

本书在线地址 http://craftinginterpreters.com/ 感谢作者 作者用近 4 年的时间持续创作和改进本书,并把其 Web 版本公开在网上。这本纸质书于今年 7 月出版,立刻在 Hacker News 等网络媒介上引起关注和讨论。 书中作者首先定义了一个动态类型的语言 …

如何写新闻稿?写好新闻稿的技巧与步骤

新闻稿是传递新闻事件和信息的重要手段,是传媒工作中不可或缺的一部分。写好一篇新闻稿可以让受众了解更多信息,进一步提高他们的关注度。以下是一些写好新闻稿的技巧和步骤,帮助你有效地传达新闻。1、确定新闻的核心信息在开始写新闻稿之前&…

解决doc命令startup.bat运行不了tomcat并配置tomcat服务器(超详细)

一、本文主要解决两个问题: 使用dos命令 startup.bat来运行tomcat,发现运行不了配置tomcat服务器变量 二、问题说明 2.1、启动Tomcat服务器只配置path对应的bin目录是不行的。有两个环境变量需要配置: JAVA_HOMEJDK的根CATALINA_HOMETomca…

「TCG 规范解读」第10章 TPM工作组 保护你的数字环境

可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…

项目管理中,项目经理需要具备哪些能力?

项目经理是团队的领导者,是带领项目团队对项目进行策划、执行,完成项目目标,对于项目经理来说,想要有序推进项目,使项目更成功,光有理论知识是不够的,也要具备这些能力: 1、分清主…

[ELasticSearch]-Logstash的使用

[ELasticSearch]-Logstash的使用 森格 | 2023年2月 介绍:Logstash在Elastic Stack中担当着ELK的工作,在本文主要阐述Logstash的处理流程以及一些应用案例。 文章目录[ELasticSearch]-Logstash的使用一、Logstash介绍1.1 What is Logstash?1.…

分享5款小众良心软件,好用到让人惊艳

目前win7渐渐退出视野,大部分人都开始使用win10了,笔者在日常的工作和使用中,为了能够让效率的大提升,下载了不少软件,以下的软件都是个人认为装机必备,而且都是可以免费下载,且没有插件的。 1…

Node-RED 3.0升级,新增特性介绍

前言 最近给我的树莓派上的Node-RED(以下简称NR)做了一下升级,从2.x升级到得了3.0。这是一个比较大的版本升级,在用户体验方面,NR有了有很大的提升。下面让我们一起来看一如何升级以及,3.0新增了那些特性 升级3.0 由于之前的NR是直接使用npm来进行安装的,所以此处升级…

库存管理系统-课后程序(JAVA基础案例教程-黑马程序员编著-第六章-课后作业)

【案例6-1】 库存管理系统 【案例介绍】 1.任务描述 像商城和超市这样的地方,都需要有自己的库房,并且库房商品的库存变化有专人记录,这样才能保证商城和超市正常运转。 本例要求编写一个程序,模拟库存管理系统。该系统主要包…

Mybatis持久层框架 | Mapper加载方式、目录结构解析

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Mapper(resource、class、package)加载方式 resource方式加载 通过resource或url加载单个mapper,接口文件与映射文件不在同一路径下,只能用re…

Java使用MD5加盐对密码进行加密处理,附注册和登录加密解密处理

前言 在开发的时候,有一些敏感信息是不能直接通过明白直接保存到数据库的。最经典的就是密码了。如果直接把密码以明文的形式入库,不仅会泄露用户的隐私,对系统也是极其的不厉,这样做是非常危险的。 那么我们就需要对这些铭文进…

【C++】内存管理知识

💙作者:阿润菜菜 📖专栏:C 本文目录 C/C内存区域分布 对比C语言内存管理的方式 C内存管理的方式 operator new与operator delete函数(new和delete实现的底层调用) new和delete的实现原理 malloc/free…