初识Linux · 环境变量

news2024/9/20 19:22:07

目录

前言:

命令行参数

环境变量

直接看现象

更多的环境变量

尝试理解环境变量


前言:

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

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


命令行参数

介绍命令行参数我们从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.coloradmin.cn/o/2149822.html

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

相关文章

HarmonyOS学习(十三)——数据管理(二) 关系型数据库

文章目录 1、基本概念2、运行机制3、默认配置与限制4、接口说明5、实战&#xff1a;开发“账本”5.1、创建RdbStore5.2、创建数据库5.3、增加数据5.4、删除数据5.5、修改数据5.6、查询数据5.7、备份数据库5.8、恢复数据库5.9、删除数据库 官方文档地址&#xff1a; 通过关系型…

堆的向下调整算法和TOPK问题

目录 1.什么是堆&#xff1f; 1.1 向下调整建堆的时间复杂度计算 1.2 堆的结构体设计 2.堆的功能实现&#xff1a; 2.1 堆的插入&#xff1a; 2.2 堆的删除&#xff1a; 2.3 堆排序&#xff1a; 2.4 向下调整建堆&#xff1a; 2.5 TOPK问题&#xff1a; 2.6 向上调整算…

对接金蝶云星空调用即时库存信息查询API(附JAVA实现)

文章目录 前言准备工作获取第三方授权权限与授权配置信息集成金蝶云SDK调用实现备注前言 对于有自己商品信息管理后台并且使用金蝶ERP系统管理物料的商家来说,将金蝶上物料的库存信息同步到管理后台就可以不用去金蝶上确认库存了,可以大大简化管理后台的库存变更工作,这篇文…

Call OpenAI API with Python requests is missing a model parameter

题意&#xff1a;使用 Python requests 调用 OpenAI API 时缺少 model 参数。 问题背景&#xff1a; Im trying to call OpenAI API from Python. I know they have their own openai package, but I want to use a generic solution. I chose the requests package for its f…

通义千问重磅开源Qwen2.5,性能超越Llama

Qwen2.5 新闻 9月19日云栖大会&#xff0c;阿里云CTO周靖人发布通义千问新一代开源模型Qwen2.5&#xff0c;旗舰模型Qwen2.5-72B性能超越Llama 405B&#xff0c;再登全球开源大模型王座。Qwen2.5全系列涵盖多个尺寸的大语言模型、多模态模型、数学模型和代码模型&#xff0c;每…

TransUNet: 通过Transformer的视角重新思考U-Net架构在医学图像分割中的设计|文献速递-Transformer架构在医学影像分析中的应用

Title 题目 TransUNet: Rethinking the U-Net architecture design for medical imagesegmentation through the lens of transformers TransUNet: 通过Transformer的视角重新思考U-Net架构在医学图像分割中的设计 01 文献速递介绍 卷积神经网络&#xff08;CNNs&#xff…

计算机毕业设计之:教学平台微信小程序(

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

生信初学者教程(四):软件

文章目录 RRstudioLinux系统其他软件本书是使用R语言编写的教程,用户需要下载R和RStudio软件用于进行分析。 版权归生信学习者所有,禁止商业和盗版使用,侵权必究 R R语言是一种免费的统计计算和图形化编程语言,是一种用于数据分析和统计建模的强大工具。它具有丰富的统计…

CSP-CCF★201912-2回收站选址★

一、问题描述 二、解答 代码&#xff1a; #include<iostream> #include<map> using namespace std; struct rubbish{int x;int y; }rub[1000]; int n; void input(){cin>>n;for(int i0;i<n;i){cin>>rub[i].x>>rub[i].y;} } bool has(int p,…

【machine learning-八-可视化loss funciton】

可视化lossfunction loss funciton可视化损失函数等高图 loss funciton 上一节讲过损失函数&#xff0c;也就是代价函数&#xff0c;它是衡量模型训练好坏的指标&#xff0c;对于线性回归来说&#xff0c;模型、参数、损失函数以及目标如下&#xff1a;、 损失函数的目标当然…

什么品牌超声波清洗机质量好?四大绝佳超声波清洗机品牌推荐!

在快节奏的现代生活中&#xff0c;个人物品的清洁卫生显得至关重要。眼镜、珠宝饰品、手表乃至日常餐厨用具&#xff0c;这些频繁接触的物品极易累积污渍与细菌。拿眼镜为例&#xff0c;缺乏定期清洁会让油渍与尘埃积累&#xff0c;进而成为细菌的温床&#xff0c;靠近眼睛使用…

SCDN是服务器吗?SCDN防御服务器有什么特点?

SCDN确实具有一定的防DDoS攻击能力&#xff0c;SCDN防御服务器有什么特点&#xff1f;高防SCDN通过结合内容分发网络&#xff08;CDN&#xff09;和分布式拒绝服务&#xff08;DDoS&#xff09;防护技术&#xff0c;提供了更全面的网络保护措施。在充满网络攻击的互联网时代&am…

dev c++输出中文乱码解决 printf乱码解决

把编码换成utf8就行 打开eiditor options

左手研发,右手销量,比亚迪舍弃了什么?

早买早享受&#xff0c;晚买享折扣&#xff0c;是近一年来汽车消费市场的真实写照。 A级家轿价格下探至6、7万元&#xff1b;曾经20万起步的主流B级车&#xff0c;如今只要12万元就能入手&#xff1b;即使是BBA等豪华品牌&#xff0c;也开始降价促销换销量。买车更便宜了&…

乐观锁、悲观锁

一、悲观锁 悲观锁 (Pessimistic Locking)&#xff0c;具有强烈的独占和排他特性。它指的是对数据被外界修改持保守态度。因此&#xff0c;在整个执行过程中&#xff0c;将处于锁定状态。所以&#xff0c;悲观锁是一种悲观思想&#xff0c;它总认为最坏的情况可能会出现&#x…

【Elasticsearch系列十五】强大特性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

没想到【C# ASP.NET + Vue】也能打造如此强大的健身房管理系统!告别传统管理,体验智能化的会员服务,课程安排竟然如此简单

&#x1f393; 作者&#xff1a;计算机毕设小月哥 | 软件开发专家 &#x1f5a5;️ 简介&#xff1a;8年计算机软件程序开发经验。精通Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等技术栈。 &#x1f6e0;️ 专业服务 &#x1f6e0;️ 需求定制化开发源码提…

多模态文档理解:一文读懂mPLUG-DocOwl系列模型

〔探索AI的无限可能&#xff0c;微信关注“AIGCmagic”公众号&#xff0c;让AIGC科技点亮生活〕 本文作者&#xff1a;AIGCmagic社区 刘一手 前言 随着人工智能技术的发展&#xff0c;多模态大型语言模型&#xff08;MLLMs&#xff09;在视觉-文本理解领域取得了显著进展。m…

yolov8多任务模型-目标检测+车道线检测+可行驶区域检测-yolo多检测头代码+教程

你只需看一次&#xff1a;实时且通用的多任务模型 A-YOLOM 插图 贡献 轻量化集成模型&#xff1a;我们开发了一种轻量级模型&#xff0c;能够将三个任务整合到一个统一的模型中。这对于需要实时处理的多任务场景尤其有利。自适应连接模块&#xff1a;特别为分割架构的颈部区域…

js中的 赋值 浅拷贝 和 深拷贝 详细解读

js数据类型主要分基本数据类型和引用数据类型。前者包括Number,String等&#xff0c;后者主要是Object,因此以下会针对不同的数据类型来分析,需要的朋友可以参考一下 基本数据类型&#xff08;Primary Data Types&#xff09;: String&#xff08;字符串&#xff09; Number&…