初识Linux · 环境变量

目录

前言:

命令行参数

环境变量

直接看现象

更多的环境变量

尝试理解环境变量


前言:

今天介绍的是一个较为陌生的名词,环境变量,在学习环境变量之前,我们需要一定的预备知识,这个预备知识是命令行参数,所以今天我们介绍环境变量的时候,介绍顺序是先介绍命令行参数,然后直接看有关环境变量的现象,到更多的环境变量,最后我们尝试来理解环境变量。

现在进入第一个话题,预备知识——命令行参数。


命令行参数

介绍命令行参数我们从main函数开始,相信不少人是比较疑惑的,这和C语言的main函数有什么关系?还真有,只不过是我们最开始忽略了main函数的参数而已,相信这个时候有人开始有反应了,main函数我们学习的时候确实会有人带参数,只是因为没有方法传参进行调用,也就不了了之了:

  5 int main(int argc,char* argv[])6 {7                                                                                                                                                                                                               8                                                                                                                      9   return 0;                                                                                                          10 } 

今天的命令行参数就从argc argv开始。

那么先来一段代码:

  5 int main(int argc,char* argv[])6 {7   for(int i = 0;i < argc;i++)8   {9     printf("%s\n",argv[i]);                                                                                                                                                                                   10   }11 12   return 0;13 }

为什么写这样一段代码呢?我们不妨对参数进行一点分析,int argc说明argc是一个整形,后面的argc是一个char*类型的数组,就代表说这个数组的内容是char*,那么我们应该是可以尝试进行打印的,所以我们写了如下代码,make一下之后,我们看看结果是什么:

结果是我们在命令行参数不管输入多少都会进行打印,并且打印顺序默认是从左到右,即最开始的一定是./test,那么这是为什么呢?

我们再来看一段代码:

  6 int g_val = 100;7 int main()8 {9   int a = 1;11   pid_t id = fork();12   if(id == 0)13   {14     printf("a=%d&&g_val=%d\n",a,g_val);15   }16   return 0;17 }  

打印结果:

这个打印结果很简单,这里提问,子进程为什么能打印g_val的值呢

我们都知道全局变量是在main函数栈帧创建之前就创建了的,按道理来说应该是和子进程没有关系才对,那么,子进程能打印这是怎么回事呢?

这里就得出来一个重要结论,父进程的数据,默认能被子进程看到并访问!

我们现在有了两个预备知识:

1 main函数的命令行参数可以使用,命令行参数是我们输入得来的

那么作用是什么?不要忘记我们ls的不同选项了,是不是就可以结合命令行参数,类似于通过下标的方式,来执行不同的功能了?这就是命令行参数要做的事。

2 父进程的数据默认能被子进程看到并访问

第三个知识是,我们平常输入指令的地方,也就是命令行解释器,提问,我们是输入给谁的呢?为什么我们输入了对应的指令,就可以有相应的指令运行呢?

这里,就是命令行解释器,我们平常输入的ls cd等命令,输入了之后,在进程部分我们知道它们实际上也是一个一个的进程,那么它们的父进程是什么?

不管我们写了任何的代码,不管怎么运行,不管我们使用的是任何的指令,不管带了多少个选项,它们本质都是进程,我们打印出来它们的ppid,在ps里面,查对应的ppid,就发现是bash进程。

这个场景是不是很像VS中cin的时候,等待输入?

所以实际上我们的操作都是对bash进程操作的,虽然我们是运行了子进程,但是本质都是给的bash进程。

预备知识3:

3 命令行给的指令等,都是传给bash的


环境变量

3个预备知识已经就位,首先提一个问题,ls运行的时候是进程,我们自己写的代码运行的时候./test也是进程,它们两个都是子进程,凭什么我们自己写的代码就需要./ ,要在当前路径寻找呢?ls等指令就不需要呢?

直接看现象

我们直接引出结论,因为有PATH这个环境变量的存在,我们可以使用echo打印出来看看:

这样是不行的,我们需要$符号:

我们可以看到有多个路径,以冒号为分隔符。

而且可以看到,ls的指令是在bin目录里面,在PATH里面恰好也有,而查找命令就是根据PATH里面有没有对应的路径,如果没有对应的路径,就需要我们自己指定路径了。

这是PATH的用途。

这样更加直观,我们可以指定路径,来执行我们所写的代码。

这是直接看现象部分,Linux中有全局设置,即是告诉编译器,应该去哪里寻找命令。

那么我们如果想要和系统一样,直接执行呢?也就是说我们要修改PATH,或者说将可执行文件放在PATH里面的目录里面,我们先来试试第二种,将我们对应的路径加进去:

使用该指令,将我们的可执行文件所在的文件路径加进去即可,然后就可以执行运行。

这里有一个需要注意的点,test在Linux中是一个命令,如果我们的可执行文件是test的话,就会导致结果容易混淆,这里推荐将可执行文件换个名字:

此时就好了。

这是第二种,我们来试试第一种,直接修改PATH:

此时我们直接修改,然后会发现PATH的路径只有我们赋值的,这是一种覆盖:

但是此时就会发现,bin目录的,或者是说原来的路径里面的指令都使用不了,但是我们的main还是可以使用:

好了,是不是感觉麻烦来了?什么指令都用不了了,此时,有同学会注意到为什么echo还可以使用?

这里就先埋个伏笔,我们通过这个现象,引入一个问题,我们打印出来的Hello world是来源于内存还是磁盘呢?

答案不用多说,自然是内存,那么我们使用指令的时候,bash进程肯定是要先找到指令,那么去哪里找呢?结合我们打印Hello world,我们知道是先将字符串加载到虚拟地址,也就是到了内存里面,同理,bash找指令的时候,是不是应该到虚拟内存去找?

当我们登录到Linux系统的时候,许多配置文件是先加载到了bash进程,那么环境变量是否在配置文件里面呢?当然是,所以我们能看到的PATH不过是内存级的变量,如果我们重启一下,那么我们对PATH的修改就没有用了,因为配置文件我们没有修改。

那么对于配置文件和指令,我们可以有一个结论,因为bash要执行指令的时候,需要找到该指令,那么配置文件就一定比指令先加载到bash进程里面。

既然提到了配置文件,我们不妨看几个:

对于vim来说,viminfo就是它的配置文件之一,所以我们yum的时候,是十分方便的,因为它会帮我们下载对应的配置文件,我们就不用单独配置文件了。

更多的环境变量

我们现在了解了一个环境变量,我们来看看更多的环境变量:

因为图片大小原因,这里截图部分,我们使用指令env即可查出来一张表,环境变量表,里面包好了所有的环境变量,我们每个简单介绍一下:

SHELL变量,外壳程序,可以理解为bash是它实例化的一个对象,HISTSIZE历史大小,表示该机器能存储我们指令的最大个数,我们平时使用指令是可以上翻下翻找我们使用过的指令的,那么查找是有个度,就是这个环境变量,是我们存储指令的最大数目,默认是1000.

可以使用指令history来查看我们写过的指令。HISTTIMEFORMAT历史时间格式,PWD代表当前路径,它是可以变化的,因为我们不管在哪个路径下是用pwd都可以打印当前路径,就是因为它是变化的。HOME不用多少,当前用户的家目录。

带有UTF的环境变量是表示当前的编码是什么,比如这台机器的编码就是UTF-8,下面那个让人头皮发麻的是颜色设置。

还有这些,比如PATH,USER等。

以上就是其他的环境变量。

那么我们能不能自己来点环境变量呢?当然是可以的:

难道这么简单?

这也没有找到啊?

为什么又可以打印呢?

哦~原来是因为HELLO是个本地变量,我们只需要知道一下本地变量就可以了,没啥用这东西,那么我们如何让HELLO变成环境变量呢?

export即可,如何取消我们设置的环境变量呢?

 unset即可。

尝试理解环境变量

我们首先来看一个函数,我们想要通过代码的形式,来看到环境变量,所以我们使用environ,它是一个二级指针,不出意外,指向的是一个char*的数组,那么我们打印看看:

int main()
{extern char** environ;for(int i = 0;environ[i];i++){printf("env[%d]:%s\n",i,environ[i]);}return 0;
}

欸!这个东西,怎么那么,像我们刚才看到的环境变量?对!它们就是我们刚才看到的环境变量。

那么结合我们的预备知识2,父进程的数据可以被子进程看到,我们知道最开始加载到了bash进程环境变量,可以被子进程打印出来,那么在bash里面是如何对诸多环境变量进行管理的呢?

这里的environ是二级指针的数组,供子进程使用,我们不难猜测,bash进程组织环境变量是靠的一张表,char* env里面存储的就是所有的环境变量,而environ指向的就是env数组,那么就可以通过下标的方式进行打印。

既然数据都共享了,父进程不妨直接给子进程两张表,一张表是命令行参数表,一张表是环境变量表。

此时,我们在命令行解释器输入的-a使用到了命令行参数表,环境变量表我们可以这样:

int main(int argc,char* argv[],char* env[])
{for(int i = 0;env[i];i++){printf("%s\n",env[i]);}return 0;
}

所以引入了main函数的第三个参数,env环境参数表,这里使用env[i]作为判断条件,我们还可以证明一件事,argv[] env[]都是以NULL结尾的。

看一个库里面的函数,叫做getenv,简单的,我们直接实例代码即可:

int main(int argc,char* argv[],char* env[])
{char* str = getenv("PATH");if(str){printf("%s\n",str);}return 0;
}

简而言之,getenv就是用来查找环境变量的。

所以现在查找环境变量有三种方式,一种是getenv,一种是main函数的参数,一种是environ二级指针。

我们现在进入最后一个话题,为什么我们最开始修改了PATH,但是仍然可以执行echo命令呢?

我们如果export一个环境变量,env里面可以查找到:

但是我们结合父进程的数据能被子进程看到,但是子进程的数据不应该被父进程看到这个点,难道bash执行export不会创建子进程吗?

是的,如果创建了子进程,bash的env表就是不能看到HELLO,所以这种指令是特殊指令,叫做内建命令,是由bash自己来执行的,不是创建了子进程的。

到此,环境变量就结束了!尚未不清楚的点后续更新~


感谢阅读!

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

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

相关文章

htop 命令:系统状态监控

一、命令简介 ​htop ​是一个互动式的进程查看器&#xff0c;它是 top ​命令的增强版本&#xff0c;提供了更丰富的功能和更好的用户界面。htop ​显示了系统的实时进程和资源使用情况&#xff08;比如 CPU 和 memory 占用情况&#xff09;&#xff0c;允许用户进行交互式操…

Vue2+vue-office/excel 实现在线加载Excel文件预览

附件预览无数据&#xff1f; 竟然是样式问题&#xff0c;必须加上style"height: 100vh;"。。。。。。。。。。。。。

HarmonyOS元服务与卡片

元服务与卡片 文章目录 一、元服务1.介绍2.常见元服务项目步骤 二、卡片1.介绍2.卡片的创建3.卡片的数据的变更4.卡片的进程间通讯4.1使用工具包4.2使用步骤 5.卡片路由postCardAction&#xff1a;快速拉起后台5.1格式5.2快速拉起指定页面--router5.3调用后台功能--call5.3卡片…

0.5.4 知识库管理微调

014 Knowledge Settings - ApiHughow to set knowledge configuration ApiHug Api design Copilot.https://apihug.com/zhCN-docs/idea/014-settings-knowledge 如何在ApiHug Api design Copilot配置团队知识库。 ​什么是知识库 &#x1f381; 团队共享设计标准共识, Team-s…

[数据集][目标检测]不同颜色的安全帽检测数据集VOC+YOLO格式7574张5类别

重要说明&#xff1a;数据集里面有2/3是增强数据集&#xff0c;请仔细查看图片预览&#xff0c;确认符合要求在下载&#xff0c;分辨率均为640x640 数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件…

CSS-Grid布局详解

前言 Grid 栅格布局 是 CSS 语言中非常强大的种布局&#xff0c;它提供了丰富的工具属性&#xff0c;可以轻松实现复杂且灵活的布局设计&#xff0c;因此想要完美使用CSS Grid 也有一定的难度和复杂性&#xff0c;我自己也是花了不少时间才真正掌握它的使用&#xff0c;在这篇…

【人工智能学习笔记】7_智能语音技术基础

智能语音技术概述 智能语音技术通过对语音进行分析、理解和合成,是计算机设备实现“能听会说”、具备自然语音交流的技术能力。其涉及的范围主要有: 语音合成技术语音识别技术语音测评技术语音降噪与增强技术…智能语音技术的研究内容 智能语音技术的研究难点 智能语音技术…

Flutter 安装,配置,运行第一个app 1

起因&#xff0c; 目的: flutter, 其实几年前&#xff0c;我就写过。 当时纯属是个人兴趣&#xff0c;随意探索。 当时我也写了几篇笔记: 比如这一篇还有这个 flutter&#xff0c;其实不难&#xff0c;比较繁琐&#xff0c;小的知识点很多. flutter&#xff0c; 又是环境配…

SVN泄露 CTFHUB 解题笔记

参考大佬链接CTFHub | SVN泄露_ctfhubsvn泄露-CSDN博客 先下载插件 然后把GIT&#xff1b;里面的代码 乱盘上去 python2 不知道需不需要 先装了 再说。。。我的是裸机~ 开始作妖模式 Ubuntu 22.10 | Installati.one 上面一行的代码 链接 下面 插件 GITHUB页面下面的代码 d…

vue h5 蓝牙连接 webBluetooth API

webBluetooth API的 缺点&#xff0c; 只能固定的几个浏览器使用&#xff0c;其他浏览器打开使用不了这个api&#xff0c;ios也用不了&#xff0c;因为ios的浏览器内核都不属于webBluetooth 的条件 因为使用的地方比较多 所以在main.js 进行全部封装 // 蓝牙服务 Vue.proto…

Linux基础4-进程1(操作系统,进程介绍,Linux进程相关命令,getpid,fork)

上篇文章&#xff1a;Linux基础3-基础工具4&#xff08;git&#xff09;&#xff0c;冯诺依曼计算机体系结构-CSDN博客 本章重点&#xff1a; 1. 操作系统简介 2. 什么是进程&#xff1f; 3. 在Linux使用命令查看进程&#xff08;ps&#xff09; 4. getpid&#xff0c;getppid,…

基于区块链的相亲交易系统源码解析

随着区块链技术的成熟与发展&#xff0c;其去中心化、不可篡改的特性逐渐被应用于各行各业。特别是在婚恋市场中&#xff0c;区块链技术的应用为相亲平台带来了新的可能性 。本文将探讨如何利用区块链技术构建一个透明、高效的相亲交易系统&#xff0c;并提供部分源码示例。 区…

秋招八股总结

transformer 损失函数 交叉熵的原理 公式 xi是true_label&#xff0c;yi是神经网络预测为正确的概率 对比学习loss 对比学习损失函数 InfoNEC Loss&#xff08;bge中也用的这个&#xff09; SimCSE的主要思想&#xff1a;同一句话通过不同的drop out作为正例&#xff0…

halcon中的放射变换

放射变换原理 怎样计算放射变换 仿射变换affine是透视变换的子集 - 仿射矩阵 仿射变换矩阵为2*3的矩阵&#xff0c;第三列的元素起着平移的作用&#xff0c;前面两列的数字对角线上是缩放&#xff0c;其余为旋转或者斜切的作用 - 计算仿射矩阵只需要3对不共线的点 定义 指…

SOMEIP_ETS_117: SD_Entry_references_options_of_same_kind

测试目的&#xff1a; 验证DUT能够处理一个包含两种相同类型选项的SubscribeEventgroup消息&#xff0c;DUT可以选择拒绝订阅尝试或忽略该请求。 描述 本测试用例旨在确保DUT遵循SOME/IP协议&#xff0c;当接收到一个包含重复相同类型选项的SubscribeEventgroup消息时&#…

英飞凌 PSoC6 RT-Thread 评估板简介

概述 2023年&#xff0c;英飞凌&#xff08;Infineon&#xff09;联合 RT-Thread 发布了一款 PSoC™ 62 with CAPSENSE™ evaluation kit 开发板 &#xff08;以下简称 PSoC 6 RTT 开发板&#xff09;&#xff0c;该开发套件默认内置 RT-Thread 物联网操作系统。PSoC 6 RTT 开…

window.open()地址栏隐藏问题解决方案

问题 使用window.open打开一个页面时&#xff0c;想要隐藏地址栏&#xff0c;但是无效。 window.open (test.html,newwindow,height100,width400,top0,left0,toolbarno,menubarno,scrollbarsno, resizableno,locationno, statusno)由于浏览器区别和安全问题&#xff0c;浏览器…

idea工具,一个项目开启多个项目运行窗口并且显示端口,service窗口

在多数情况下&#xff0c;通常会打开一个项目&#xff0c;里面有多个项目需要运行&#xff0c;这里教大家怎么开启多个窗口来查看项目运行状态&#xff0c;最终效果如下。 点击view -> Tool Windows-> Services 点击services之后&#xff0c;会在下面出现这个页面。 点击…

8.1差分边缘检测

基本概念 差分边缘检测是一种图像处理技术&#xff0c;用于检测图像中的边缘。边缘是指图像中灰度值发生显著变化的区域。差分边缘检测通常通过计算图像的梯度来实现&#xff0c;梯度反映了灰度值的变化率。在OpenCV中&#xff0c;可以使用不同的算子来检测不同方向的边缘&…

R18 NES 之SSB-less SCell operation for inter-band CA

在TR 21.918 Summary of Rel-18 Work Items 中可以看到SSB-less SCell operation for inter-band CA 是Network energy savings for NR 的一部分,其中还包括cell DTX/DRX 等等其他内容。 网络节能是 5G/NR 成功的关键,可以减少对环境的影响(温室气体排放)并节省运营成本。R…