【Linux】环境变量

一、概念

二、环境变量PATH

三、Linux中的环境变量

四、环境变量相关操作

4.1 unset

4.2 getenv

4.3 main函数传参

(1)命令行参数

(2)环境变量表

4.4 常规命令与内建命令

4.5 第三方变量environ


一、概念

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,是系统提供的一组name/value形式的变量,相当于给系统或用户应用程序设置的一些参数

每个环境变量都分别有自己不同的用途。我们先来认识其中一个环境变量:PATH,并通过这个变量来简单了解一下环境变量的作用。


二、环境变量PATH

在Linux中,我们直接输入命令就可以执行,但是如果要运行一个程序,则需要带上路径

例如我们运行当前路径下的程序时,就需要加上相对路径才能运行 

如果不加路径,就会报错,提示"command not found"

这说明命令在执行的时候是需要被查找的,在哪里查找呢?实际上就是在环境变量PATH的路径下查找。

我们可以通过echo $PATH查看PATH环境变量的内容:

可以看到PATH实际上就是许多个路径,当我们运行命令时,系统就会在这些路径下查找是否有对应的命令,如果有则执行。

进行猜想:如果我们将一个路径添加到PATH环境变量中,是否能够像运行命令一样来运行该路径下的程序呢?

首先我们将PATH的内容修改一下:

当我们修改PATH时,会将原来的值覆盖,如果我们想实现在原来的值后面添加一个路径,则需要在路径前面加上$PATH

现在再查看一下PATH环境变量的内容,可以看到我们的路径已经添加进去了:

接下来,我们通过export PATH命令将修改后的PATH重新加入环境变量中,然后我们就可以通过命令的方式来运行我们的二进制程序了:

需要知道的是,修改PATH环境变量只在当前用户下有效,并且当重启终端后就会复原,因为这种对环境变量的修改是临时性的。


三、Linux中的环境变量

Linux中常见的环境变量有: 

  • PATH:指定系统查找可执行文件的路径
  • HOME:指定用户的主工作目录
  • SHELL:指定当前用户默认使用的Shell
  • USER:当前用户名
  • LANG:系统的默认语言
  • ......

如果我们想查看所有的环境变量,可以使用env命令


四、环境变量相关操作

4.1 unset

除了前面提到的echo、export和env,如果我们想取消一个环境变量可以用unset命令

例如我们随便添加一个环境变量:

要想删除这个环境变量,通过unset + 变量名就可以删除了

4.2 getenv

getenv是一个C库函数,以下是它的声明

char *getenv(const char *name)

这个函数可以传入一个环境变量名,返回该变量名的值,例如我们运行以下代码:

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

int main()
{
    char name[40];
    strcpy(name, getenv("USER"));
    if(strcmp(name, "root") == 0)
    {
        printf("root用户\n");
    }
    else
    {
        printf("普通用户\n");                                                                                                                                                                       
    }
    return 0;
}

可以看到我们向getenv函数中传入了环境变量USER,所以它会返回当前用户名。

运行代码,结果如下:

4.3 main函数传参

(1)命令行参数

main函数也是函数,只要是函数就会被调用,也可以传入参数,所以我们的main函数实际上也是可以带参的:

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

}

这两个参数就是main函数的命令行参数。 

但是main函数中的这两个参数是什么意思呢?

首先可以观察到,argv是一个指针数组,存放的是char*类型的指针,所以可以知道这个数组用于存放字符串。

而另一个参数argc,实际上就是数组argv中存放的元素数量。

现在,我们来观察一下argv中到底存放了什么东西,运行下面的这段代码

#include <stdio.h>

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

结果如下:

可以看到此时argv数组中存放了我们输入的命令字符串

我们知道,在输入命令的时候是可以带一些选项的,如果我们在运行自己的二进制程序时也带一些选项的话,结果就会变成这样:

通过观察我们就能发现,在输入命令时,如果我们的命令中带有选项,那么就会被打散成多个字符串,而argv数组中存放的就是这些字符串的地址,并且最后一个位置是NULL。

因为我们在Windows下不用通过命令来运行代码,所以平时我们基本用不到命令行参数。但是在Linux下这两个参数就有它们的用途了,例如:

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

int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("%s -[a|b|c|d]\n", argv[0]);
        return 0;
    }
    else if(strcmp(argv[1], "-a") == 0)
    {
        printf("function 1\n");
    }
    else if(strcmp(argv[1], "-b") == 0)
    {
        printf("function 2\n");
    }
    else if(strcmp(argv[1], "-c") == 0)
    {
        printf("function 3\n");
    }
    else if(strcmp(argv[1], "-d") == 0)
     {
        printf("function 4\n");                                                                                                 
    }
    return 0;
}

运行代码,结果如下:

可以看到,当我们输入不同的选项时,就可以执行不同的功能了,这就是命令行参数的用途。

命令行参数可以为指令、工具、软件等提供命令行选项的支持

 命令行参数不只是C/C++需要支持,几乎所有的语言都需要支持命令行参数,因为用这些语言写出来的软件都需要根据选项来定制化不同的功能。

(2)环境变量表

实际上,main函数中不止能传两个参数,还有第三个参数——环境变量表

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

}

env和argv一样,都是一个存放char*类型的指针数组,而通过它的名字我们就可以知道其中存放的就是环境变量。通过下面这段代码进行验证:

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

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

结果如下:

可以看到,env中的环境变量和我们输入env命令打印出来的环境变量是一样的。

当我们运行二进制程序时,这个进程就是bash的子进程。那么是否可以认为子进程可以继承父进程的环境变量呢?

实际上我们运行的进程,都是bash的子进程,而bash在启动的时候会从操作系统的配置文件中读取环境变量信息。在创建子进程的时候,也会通过传参等方式将环境变量继承给子进程

环境变量通常具有全局属性,可以被子进程继承下去。除了环境变量,还有不具有全局属性的本地变量,例如:

这种变量是无法被子进程继承的,也不会存在于环境变量表中。在命令行中直接定义的变量就叫做本地变量

如果我们想把本地变量存到环境变量表中,用export命令就可以了

前面说过,子进程会继承父进程的环境变量信息,那么我们再运行一次程序试试:

可以看到,当前我们的程序就已经拿到了新增的VAL环境变量了

现在我们用unset命令把这个环境变量删除,并重新将其设置为一个本地变量。

4.4 常规命令与内建命令

前面提到过,子进程无法继承父进程的本地变量,只能继承环境变量

而我们在Linux中输入的命令实际上也是bash的子进程,所以理应也无法读取到bash的本地变量

但是为什么我们用echo命令还能打印出bash的本地变量呢?

其实并不是所有的命令都要创建子进程,Linux中分为两种命令:

  • 常规命令:通过创建子进程完成
  • 内建命令:不创建子进程,而是由bash亲自执行

例如cd命令如果通过创建子进程来完成,由于进程的独立性,它只会修改子进程的工作路径。但是实际上是父进程的路径发生更改,因此cd其实也是一个内建命令。

4.5 第三方变量environ

我们不一定要通过传参的方式来获取环境变量表,还可以通过environ——一个指向父进程的环境变量表的指针,来获取环境变量

#include <stdio.h>
#include <unistd.h>

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

environ是在libc中定义的全局变量,没有包含在任何头文件中,所以在使用时需要用extern声明

运行代码,结果如下:

如有错误或遗漏欢迎在评论区指出

完.

评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值