Linux系统 环境变量

环境变量

  • 写在前面
  • 概念
  • 查看环境变量
    • main函数的参数
      • argc & argv
      • env
  • bash环境变量

写在前面

对于环境变量,本篇主要介绍基本概念及三四个环境变量 —— PATH、HOME、PWD。其中 PATH 作为 “ 敲门砖 ”,我们会更详细讲解;理解环境变量的全局属性 —— 环境变量是可以被子进程继承(注意区分 C++ 里的继承);环境变量的组织方式。其次会介绍命令行参数 —— main 函数的参数。

概念

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

我们在编写 C/C++ 代码的,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。

环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。

LInux操作系统本身就是一个用C语言写的程序,操作系统可以在运行过程中开辟空间。环境变量的本质,就是在操作系统运行过程中,为自己开辟的空间,存储了一些重要的信息。

为了更好的理解环境变量的作用,现在我们先来思考一个问题,我们在执行指令的过程之中,可以直接输入指令的名字,但是我们自己写的可执行程序,一定要加上绝对路径或者相对路径才可以运行,这是为什么呢?

其实这个过程之中,环境变量的作用就显现出来了。

PATH:一个环境变量,存储着多个路径,在这些路径下面的可执行程序,可以直接执行。

PATH是我们讲解的第一个重要的环境变量,我们现在尝试观察这个环境变量。

echo $xxx:查看xxx环境变量的内容

在这里插入图片描述
可以看出这个环境变量是由多个路径组成的,每个路径由分开。
因此我们只需要把自己的可执行程序放在这里面某一个路径下面,我们自己写的可执行程序就也可以当作指令来执行了。而这个工作就是把自己写的软件安装到系统之中。

我们也可以想办法把自己的路径加到PATH环境变量中。

xxx=:修改环境变量的值

如果我们当前路径下有一个可执行程序test.exe并且我们将其路径加到了PATH中,那么我们就可以直接执行这个程序,但是原来PATH中的内容会被我们的修改直接覆盖。导致原有的ls,pwd,mkdir等等指令全部执行不了了。但是不用惊慌,我们只需要关闭xshell,然后重启,此时PATH就会恢复原先的值。

我们再来看看几个常用的的环境变量。

USER:记录当前的用户
PWD:记录当前路径
HOME:记录家目录

在这里插入图片描述

我们还可以自己定义一些环境变量:

export xxx=:定义xxx环境变量

在这里插入图片描述
不过我们自己定义的环境变量在重新启动的时候也会失效。

还有一个与环境变量相关的重要指令。

env:输出所有环境变量。

展示部分如下。
在这里插入图片描述

查看环境变量

通过之前的认识,我们知道可以通过env来查看所有的环境变量,也可以通过echo $xxx查看单个环境变量,但是这些都是在命令行中操作的,如果我们想在可执行程序中查看需要如何做呢?

  • getenv

getenv是一个函数,其定义在<stdlib.h>中。功能是:输入一个字符串作为参数,该函数输出该字符串对应的环境变量的内容。

当前test.exe程序内容如下:

#include <stdio.h>      
#include <stdlib.h>      
      
int main()      
{      
    const char* path = getenv("PATH");      
    const char* home = getenv("HOME");      
      
    printf("PATH = %s\n", path);      
    printf("HOME = %s\n", home);    
    
    return 0;    
}      

在这里插入图片描述

main函数的参数

也许你或许听说过,main函数也是有参数的,但是在学习C/C++的过程中,这个参数好像可写可不写,学习环境后,我们就可以了解一下这些变量的意义是什么了。

argc & argv

main的前两参数分别是argc和argv,传参形式如下:

int main(int argc, char* argv[])  
{}

可见,argcint类型的变量,而argv是一个char*的数组。还记得我们刚刚的env指令内容吗?其实它们两个的结构是一样的。argv每个元素都是char*类型,分别指向一个字符串,argv的最后一个元素也是NULL,用于标识argv的数组结尾。而argc代表了argv中元素的个数,所以我们既可以通过NULL来判断argv结尾,也可以通过argc来判断结尾。在test中执行如下代码,来看看argv中存储了什么:

#include <stdio.h>      
      
int main(int argc, char* argv[])      
{      
    for(int i = 0; i < argc; i++)      
    {      
        printf("argv[%d]: %s\n", i, argv[i]);      
    }    
    
    return 0;    
}        

在这里插入图片描述
现在argv中只有一个元素,即字符串"./test.exe"

给./test.exe加几个选项试试,./test.exe -a -b -c

在这里插入图片描述
可以得出argv参数内部,存储的是调用可执行程序时,输入的选项
通过argv存储的内容我们就可以根据不同选项执行不同的内容。

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

int main(int argc, char* argv[])    
{              
    bool flagA = false, flagB = false, flagC = false;    
               
    for(int i = 0 ; i < argc; i++)    
    {          
        if (strcmp(argv[i], "-a") == 0)    
            flagA = true;//说明输入了-a选项    
        else if (strcmp(argv[i], "-b") == 0)    
            flagB = true;//说明输入了-b选项    
        else if (strcmp(argv[i], "-c") == 0)    
            flagC = true;//说明输入了-c选项    
    }          
               
    printf("正在执行 test.exe\n");    
               
    if(flagA)    
        printf("功能a执行中...\n");    
    if(flagB)    
        printf("功能b执行中...\n");    
    if(flagC)    
        printf("功能c执行中...\n");    
        
    return 0;                                                                                               
}   

我们使用的绝大多数指令都是有很多选项的,我们通过输入不同的选项,让程序执行不同的功能,而程序就是通过识别argv,来判断用户输入了哪些选项,进而执行特定的功能的。

在我们向bash输入一大段指令的时候,指令本质就是一个字符串,bash会把字符串拆解为一个个小小的字符串,然后把他们整合到一个叫做命令行参数表的东西中,命令行参数表其实就是一个指针数组,而argv参数可以接收bash维护的数组,在程序内部使用。


env

main函数的第三个参数叫做env,其实它也是一个char*类型的指针数组,类型为char**

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

这个参数和指令env的内容完全一致的。存储了所有环境变量,并且以NULL结尾。

#include <stdio.h>    

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

    return 0;
}

bash环境变量

其实环境变量是可以继承的,可以通过下面的代码证明。

#include <stdio.h>                                                                                        
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char* argv[], char* env[])    
{    
    pid_t id = fork();    
        
    if(id == 0)//子进程    
    {    
        for(int i = 0; i < 3; i++)    
        {    
            printf("child:  env[%d]: %s\n", i, env[i]);                                                           
        }    
    }    
    else//父进程    
    {    
        for(int i = 0; i < 3; i++)    
        {    
            printf("father: env[%d]: %s\n", i, env[i]);    
        }    
    }    
    
    return 0;    
}  

通过fork创建了一个子进程,然后父子进程分别输出env这个数组中的前三个字符串。

输出结果:
在这里插入图片描述

可以看到父子进程都可以正常使用env,说明子进程是可以继承父进程的环境变量表的。而在所有命令行调用的进程中,都是bash的子进程,因此我们的在命令行调用的进程可以继承bash的环境变量表。只有我们登录了系统的时候,bash才会被创建,之前我们就知道,bash要维护一张环境变量表,那么bash的环境变量是怎么来的?其实这些环境变量是存储的在磁盘上的,而我们启动bash的时候,会把这些环境变量从磁盘上拷贝到内存中,组成一张环境变量表,我们访问环境变量实际上是在访问内存中的环境变量,我们修改环境变量实际上也是在修改内存中的环境变量,不会影响磁盘中的环境变量。

因此当我们重新启动Xhell时,bash都会重新从磁盘中拷贝一次环境变量,这样我们之前所做的修改或者自己添加的环境变量都会被覆盖重置

另:在家目录中,有一个叫做.bash_profile的隐藏文件 ,其内部存储的就是环境变量。这个就是我们每次重新启动从磁盘拷贝环境变量的文件内容。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

BFS(广度优先搜索)——搜索算法

BFS&#xff0c;也就是广度&#xff08;宽度&#xff09;优先搜索&#xff0c;二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS&#xff08;深度优先搜索&#xff09;。从字面意思也很好理解&#xff0c;DFS就是一条路走到黑&#xff0c;BFS则是一层一层地展开。…

SpringCloud基础二(完结)

HTTP客户端Feign 在SpringCloud基础一中&#xff0c;我们利用RestTemplate结合服务注册与发现来发起远程调用的代码如下&#xff1a; String url "http://userservice/user/" order.getUserId(); User user restTemplate.getForObject(url, User.class);以上代码就…

Spring Bean 容器

技术成长&#xff0c;是对场景设计细节不断的雕刻&#xff01; 你觉得自己的技术什么时候得到了快速的提高&#xff0c;是CRUD写的多了以后吗&#xff1f;想都不要想&#xff0c;绝对不可能&#xff01;CRUD写的再多也只是能满足你作为一个搬砖工具人&#xff0c;敲击少逻辑流…

【react+redux】 react使用redux相关内容

首先说一下&#xff0c;文章中所提及的内容都是我自己的个人理解&#xff0c;是我理逻辑的时候&#xff0c;自我说服的方式&#xff0c;如果有问题有补充欢迎在评论区指出。 一、场景描述 为什么在react里面要使用redux&#xff0c;我的理解是因为想要使组件之间的通信更便捷…

利用腾讯云cloud studio云端免费部署deepseek-R1

1. cloud studio 1.1 cloud studio介绍 Cloud Studio&#xff08;云端 IDE&#xff09;是基于浏览器的集成式开发环境&#xff0c;为开发者提供了一个稳定的云端工作站。支持CPU与GPU的访问。用户在使用 Cloud Studio 时无需安装&#xff0c;随时随地打开浏览器即可使用。Clo…

基于VMware的ubuntu与vscode建立ssh连接

1.首先安装openssh服务 sudo apt update sudo apt install openssh-server -y 2.启动并检查ssh服务状态 到这里可以按q退出 之后输入命令 &#xff1a; ip a 红色挡住的部分就是我们要的地址&#xff0c;这里就不展示了哈 3.配置vscode 打开vscode 搜索并安装&#xff1a;…

四川正熠法律咨询有限公司正规吗可信吗?

在纷繁复杂的法律环境中&#xff0c;寻找一家值得信赖的法律服务机构是每一个企业和个人不可或缺的需求。四川正熠法律咨询有限公司&#xff0c;作为西南地区备受瞩目的法律服务提供者&#xff0c;以其专注、专业和高效的法律服务&#xff0c;成为众多客户心中的首选。 正熠法…

【优先算法】专题——位运算

在讲解位运算之前我们来总结一下常见的位运算 一、常见的位运算 1.基础为运算 << &&#xff1a;有0就是0 >> |&#xff1a;有1就是1 ~ ^&#xff1a;相同为0&#xff0c;相异位1 /无进位相加 2.给一个数 n&#xff0c;确定它的二进制表示…

Android --- handler详解

handler 理解 handler 是一套Android 消息传递机制&#xff0c;主要用于线程间通信。 tips&#xff1a; binder/socket 用于进程间通信。 参考&#xff1a; Android 进程间通信-CSDN博客 handler 就是主线程在起了一个子线程&#xff0c;子线程运行并生成message &#xff0c;l…

【线程】基于阻塞队列的生产者消费者模型

文章目录 1 生产者消费者模型2 阻塞队列2.1 成员变量2.2 消费者操作2.3 生产者生产 3 总结 1 生产者消费者模型 在多线程环境中&#xff0c;生产者消费者模型是一种经典的线程同步模型&#xff0c;用于处理生产者线程与消费者线程之间的工作调度和资源共享问题。在这个模型中&a…

解决PyG安装中torch-sparse安装失败问题:详细指南

1 问题描述 最近在学习GNN&#xff0c;需要使用PyTorch Geometric&#xff08;PyG&#xff09;库。在安装PyG的过程中&#xff0c;遇到了torch-sparse安装失败的问题&#xff0c;错误提示为&#xff1a; ERROR: Failed building wheel for torch-sparse本文将详细记录问题的解…

4 [危机13小时追踪一场GitHub投毒事件]

事件概要 自北京时间 2024.12.4 晚间6点起&#xff0c; GitHub 上不断出现“幽灵仓库”&#xff0c;仓库中没有任何代码&#xff0c;只有诱导性的病毒文件。当天&#xff0c;他们成为了 GitHub 上 star 增速最快的仓库。超过 180 个虚假僵尸账户正在传播病毒&#xff0c;等待不…

【B站保姆级视频教程:Jetson配置YOLOv11环境(六)PyTorchTorchvision安装】

Jetson配置YOLOv11环境&#xff08;6&#xff09;PyTorch&Torchvision安装 文章目录 1. 安装PyTorch1.1安装依赖项1.2 下载torch wheel 安装包1.3 安装 2. 安装torchvisiion2.1 安装依赖2.2 编译安装torchvision2.2.1 Torchvisiion版本选择2.2.2 下载torchvisiion到Downloa…

自动化软件测试的基本流程

一、自动化测试的准备 1.1 了解测试系统 首先对于需要测试的系统我们需要按照软件需求说明书明确软件功能。这里以智慧养老系统作为案例进行测试&#xff0c;先让我们看看该系统的登录界面和用户管理界面。 登录界面&#xff1a; 登录成功默认界面&#xff1a; 用户管理界面…

前端力扣刷题 | 6:hot100之 矩阵

73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 法一&#xff1a; var setZeroes function(matrix) {let setX new Set(); // 用于存储需要置零的行索引let setY new Set(); //…

SLAM技术栈 ——《视觉SLAM十四讲》学习笔记(一)

《视觉SLAM十四讲》学习笔记&#xff08;一&#xff09; 第2讲 初识SLAM习题部分 第3讲 三维空间刚体运动3.1 左手系与右手系3.2 齐次坐标3.3 旋转矩阵与变换矩阵3.4 正交群与欧式群3.5 旋转向量与欧拉角3.6 实践Eigen线性代数库3.6.1 QR分解(QR decomposition) 3.7 四元数到其…

自动驾驶---两轮自行车的自主导航

1 背景 无人驾驶汽车最早出现在DARPA的比赛中&#xff0c;从那个时刻开始&#xff0c;逐渐引起全球学者的注意&#xff0c;于是从上个世纪开始各大高校院所开始了无人汽车的研发。直到这两年&#xff0c;无人驾驶汽车才开始走进寻常百姓家&#xff0c;虽然目前市面上的乘用车还…

Spring Boot 2 快速教程:WebFlux处理流程(五)

WebFlux请求处理流程 下面是spring mvc的请求处理流程 具体步骤&#xff1a; 第一步&#xff1a;发起请求到前端控制器(DispatcherServlet) 第二步&#xff1a;前端控制器请求HandlerMapping查找 Handler &#xff08;可以根据xml配置、注解进行查找&#xff09; 匹配条件包括…

优选算法的灵动之章:双指针专题(一)

个人主页&#xff1a;手握风云 专栏&#xff1a;算法 一、双指针算法思想 双指针算法主要用于处理数组、链表等线性数据结构中的问题。它通过设置两个指针&#xff0c;在数据结构上进行遍历和操作&#xff0c;从而实现高效解决问题。 二、算法题精讲 2.1. 查找总价格为目标值…

Intel 与 Yocto 项目的深度融合:全面解析与平台对比

在嵌入式 Linux 领域&#xff0c;Yocto 项目已成为构建定制化 Linux 发行版的事实标准&#xff0c;广泛应用于不同架构的 SoC 平台。Intel 作为 x86 架构的领导者&#xff0c;在 Yocto 生态中投入了大量资源&#xff0c;为其嵌入式处理器、FPGA 和 AI 加速硬件提供了完整的支持…