Linux的环境变量

环境变量在操作系统中起到指定运行环境参数的作用,如PATH决定了命令的搜索路径。当我们直接使用命令时,操作系统会根据PATH查找二进制文件。编译的二进制文件若要直接运行,需将其路径添加到PATH中。环境变量具有全局性,能被子进程继承,通过getenv函数可以获取环境变量的值。bash通过main函数的env参数继承环境变量,argv参数则用于处理命令行参数。
摘要由CSDN通过智能技术生成

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

实际上,我们在shell中使用的各种命令实际上都是一个个二进制文件,它们都在 shell 的默认搜索路径 /usr/bin 下;

比如 'ls' ,'pwd','whoami'等等;

比如我们在命令行里输入: ls /usr/bin 时,我们就能够查看到我们平时会使用的一些命令;

 

 

 

 但是我们平时编译出来的二进制文件却不能像这些二进制文件一样,能够直接使用:

 

 

只能够通过 "./myprocess" 的形式来使用我们编译的二进制文件;

实际上这是因为环境变量的存在才导致我们能够直接使用命令;

而环境变量实际上就是我们登录到操作系统时,操作系统自己根据配置来

常用的环境变量

1.PATH:指定命令的搜索路径

2.HOME:指定用户的主工作目录

3.SHELL:当前的shell,值通常是 /bin/bash

4.USER:当前用户

 之所以我们能够直接使用命令就是因为 PATH 命令的存在;

当我们 不带 ' ./ ' 而是直接输入一个二进制文件的名称的时候,操作系统就会根据PATH提供的路径去寻找是否有该二进制文件;

而带上 './' 就表示二进制文件在本文件夹,不用在PATH中去寻找该命令;

那么我们怎样做才能使我们所编译的二进制文件可以直接使用呢?

1.将二进制文件直接放入 PATH 中的默认路径下(不推荐)

2.更改 PATH 的默认路径为当前我们所编译的文件的路径(不推荐)

3.添加当前编译的文件的路径到 PATH 中去

第一种方式会污染我们操作系统的指令池,并不推荐;

第二种方式会导致其他所有命令都无法使用,所以不推荐;

而第三种方式只是添加了一个路径,所以可以使用;

但是,我们虽然能够修改或添加PATH的默认路径;

但是我们每次重新登录 shell 的时候,这个PATH都会变回原来的模样;

这是 shell 里面配置好的文件决定的;

那么我们第三个方法应该怎么做呢?我们先要了解环境变量的相关命令

有关环境变量的命令

1.echo:显示某个环境变量值(想要查看某个环境变量必须在环境变量名前加 '$')

2.export:设置一个新的环境变量值

3.env:显示所有环境变量值

4.unset:清除环境变量

5.set:显示本地定义的shell变量和环境变量

 

我们先来看看PATH的默认搜索路径:

我们发现,默认搜索路径都是有 ':' 隔开,实际上我们在bash上输入命令的时候

shell就是根据 ':' 隔开的路径来查找指令;

而我们的第三种方法就是通过export来更改当前的 PATH ;

 

可以看到,更改了PATH之后,PATH后面多了新的搜索路径

而我们自己编译并运行的文件也能够直接运行了;

当然,我们这里只是暂时的更改,当我们重新登录shell,就会被更改回原来的样子;

 

环境变量的特性——全局性

 在代码中,全局变量能够被各个代码块所使用,而环境变量和这类似;

它能够被子进程所继承;

我们都知道我们编译并运行的进程都是bash进程的子进程,那么我们应该能够通过子进程查看父进程的环境变量,这里我们能够通过系统调用来获取环境变量——getenv;

getenv

 传递所查的环境变量的名字,找到就返回该环境变量的内容,没找到就返回null;

接下来我们实验一下

#include<stdio.h>
#include<stdlib.h>

#define PATH  "PATH"

int main()
{
        char * myenv = getenv(PATH);

        printf("PATH = %s\n",myenv);
        return 0;
}

 在这里,我们使用 getenv 函数获得对应环境变量所对应的内容并输出;

这样我们就能够清楚的了解到,环境变量是能够继承的;

我们都知道bash也是一个进程,我们能够直接用它创建一个本地变量;

但这个本地变量无法继承给子进程

 这里我们创建了一个 myval 的本地变量,它的内容为123;

#include<stdio.h>
#include<stdlib.h>

#define PATH  "PATH"
#define myval "myval"

int main()
{
        char * myenv = getenv(myval);

        printf("myval = %s\n",myenv);
        return 0;
}

 但是我们可以看到,它并非是环境变量;

但是我们可以通过export将它变为环境变量;

 这里的export可以将局部变量直接转化为环境变量而不修改它的内容;

但是若是没有内容则需要添加内容;

我们现在知道环境变量已经有了全局性,子进程能够继承父进程的环境变量;

那么是如何做到的呢?

首先需要了解环境变量的组织方式

环境变量的组织方式

每一个程序,都会有一张环境表,它是一个字符指针数组,它的每一个指针都指向一个字符串;

 

 

 就像这样,而我们之前学习的时候,知道,main 函数实际上有三个参数

                                                            1.int argc;

                                                            2.char* argv[];

                                                            3.char* env[];

其中的env就是一个环境表,其内部包含各种环境变量;

而我们的bash实际上也是一个程序,它也有它的main函数,这就是环境变量继承的原因;

那如何证明呢?

我们写下这样的代码:

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

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

 

 通过env查看环境变量;

通过创建的程序查看环境变量

 我们发现,除了最底下的程序所在的路径不同之外,其他的环境变量都是一模一样的;

这就是环境变量继承的原因;

扩展

上面提到 main 函数还有两个参数 argv 和 argc;

那么这两个参数是干什么用的呢?

这两个参数实际上是命令行参数;

argv是命令行参数的指针数组,而argc则是argv的大小;

 

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

int main(int argc,char* argv[],char* env[])
{
        for(int i = 0;i<argc;i++)
        {
                printf("argv[%d] = %s\n",i,argv[i]);
        }
        return 0;
}
myprocess:test.c
        gcc -o myprocess test.c -std=c99
.PHONY:clean
clean: 
        rm -f myprocess

 我们发现,argv[0]表示命令,后续的指针则是表示一个个指令;

这就是我们 bash 的真面目;

通过 argv 数组获取我们的命令,然后将指令一个一个分割;

最后通过指令找到对应的操作;

并且这些指令也能够继承!

总结

1.我们的环境变量是操作系统用来控制操作系统运行环境的一些指令;

比如默认搜索路径,当前使用用户等;

2.环境变量具有继承性,通过main函数的env指针数组继承;

3.我们的bash是通过env指针数组继承父进程的环境变量;

4.bash的命令则通过分割main函数的argv指针数组的命令和指令进行不同的操作;

5.main函数的所有参数都是可继承的;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值