Linux学习之路 -- 进程篇 -- 环境变量

本文将介绍环境变量的相关内容,以及相关操作

目录

一、main

二、环境变量

1.为什么要有环境变量?

2.环境变量的特性以及命令行操作

<1>命令行操作:

<2>特性:


一、main

介绍一下main函数的参数。

在一些教材上,我们经常可以看到main函数是可以带参数的。

int main(int argc, char* argv[])
{
   //......
   return 0;
}

这里我们并不知道main的参数里面存的是啥,不过可以确定的是char* 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;
}

运行结果

root@iZuf6at4ih6u7gbg2vxumnZ:~/linux/Linux-ubantu/pro-nice# 这一长串的字符是bash给我们输出的命令行字符串,我们输入的其实是一段长字符串,在这里被bash分割成了一个一个的小字符串。这里其实就是以空格为分割符,将长字符串分割成了一个一个的小字符串,并且我们将小字符串的首元素的地址放在argv这个字符数组里面。将分割的字符串个数放进argc这个变量里面。然后将对应得参数传个main即可。

所以上述的代码也可以这样写

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

那我们为什么要这样做呢?

下面用一段代码来说明其中的缘由

#include<stdio.h>
int main(int argc, char* argv[])
{
   if(argc != 2)
   {
        printf("操作错误,请输入标准命令:./Main.c -number[number属于1-3]\n");
   }
   else
   {
        if(strcmp(argv[1],"-1") == 0)
        {
            printf("funtion 1\n");
        }
        else if(strcmp(argv[1],"-2") == 0)
        {
            printf("funtion 2\n");
        }
        else if(strcmp(argv[1],"-3") == 0)
        {
            printf("funtion 3\n");
        }
        else
        {
            printf("unkown\n");
        }
   }
   return 0;

}

运行结果

这里需要输入一段命令,这段命令必需带一个选项,通过argv参数,我们就可以获取用户所需的选项,从而实现不同的功能,其实就和ls 命令带不同选项会有不同效果是一样的,系统这样做的原因也是因为这个。argc,argv就是命令行参数,这也是Linux指令选项的基础。

二、环境变量

环境变量其实和上述命令行参数有相似之处。在了解它之前我们需要知道的是,环境变量不是只有一个,而是由一堆,而且他们彼此之间没有什么关系。它们一般是系统内置的具有特殊用途的变量,这里的变量其实跟我们常用的编程语言上的变量没啥区别,本质上都是开辟空间。在系统的环境变量,本质是系统自己开辟空间,给他名字和内容即可,当然,bash也是可以开辟空间的。

1.为什么要有环境变量?

在回答这个问题之前,我们先看一个现象,在每一次运行一个可执行程序时,我们总要在这个程序名前面加上绝对或者相对路径,而在执行系统命令(本质上也是可执行程序)时,就不需要加上路径?

要运行一个程序的前提是我们必需找到这个程序,那为什么系统指令不要提供路径,系统就能找到它们呢?其实这就是因为环境变量PATH, 我们可以用echo $PATH查看这个环境变量。这个变量其实是一个长字符串(冒号为分割符),里面记录了一些路径,当我们调用系统指令时,系统就会沿着PATH所提供的路径依次搜索这个命令对应的可执行程序。而我们自己写的程序并没有添加到这个路径里面,所以系统不知道从哪里开始寻找,所以在运行时,前面就要加上特定的路径。

如果我们想要让我们自己写的可执行程序不用加路径,做法有两种,一是把我们写的可执行程序直接加到上述路径下的目录中,不过不建议这样做。另一种是把我们当前程序的路径添加到PATH变量中即可。使用“ PATH = 当前程序的绝对路径 :$PATH(这个一定要加,要不然原来的路径就全被覆盖掉了) ”  命令,就可以把当前可执行程序的路径添加进PATH变量中。如果我们直接让PATH = 当前程序的绝对路径,这样会导致其他的系统指令全部失效。如果发生这种情况,直接重新登录即可,这是因为我们修改的PATH是在内存里面的,不是磁盘上的。当我们重新登录系统时,系统会重新从磁盘的配置文件/脚本里加载PATH变量。在./bash_profile里面可以配置一些环境变量,系统会从这个文件里读取环境变量的导入脚本,不建议随便配置。

前面说过,环境变量不止一个,而是有很多个,它们记录了用户的一些相关信息,比如登录者是谁,当前在哪条路径下等等。我们可以用env命令查看当前所有的环境变量

这些信息就是为什么操作系统始终知道登录的用户是谁,在哪里等等。如果想要查找特定的环境变量,使用"echo $变量名"即可

下面是我搜集的一些环境变量所代表的含义,如有缺漏,可自行补充。

  1. HOME - 用户的主目录路径。
  2. PATH - 执行命令时要搜索的目录列表,目录之间用冒号(:)分隔。
  3. PWD - 当前工作目录的路径。
  4. USER - 当前登录的用户名。
  5. SHELL - 当前用户的登录shell的路径。
  6. HOSTNAME - 当前系统的主机名。
  7. TERM - 当前终端的类型。
  8. EDITOR - 用户默认的文本编辑器的路径。
  9. PAGER - 用户默认的分页器的路径。
  10. MAIL - 用户邮箱文件的路径,通常是/var/spool/mail/username
  11. LANG - 定义了系统默认的语言和字符集,如en_US.UTF-8
  12. LC_ALL - 覆盖所有地区的设置,如果设置了LC_ALL,它会优先于LANG
  13. DISPLAY - X Window系统使用的显示服务器和屏幕的名称,格式通常是hostname:display_number.screen_number
  14. SSH_AUTH_SOCK - SSH认证代理的UNIX域套接字的路径。
  15. HTTP_PROXY/HTTPS_PROXY - HTTP/HTTPS代理服务器的地址。
  16. NO_PROXY - 不使用代理服务器的地址列表。
  17. LD_LIBRARY_PATH - 动态链接器搜索共享库的路径。
  18. MANPATH - 搜索手册页的路径。
  19. PS1 - 主提示符,是你在终端看到的命令提示符

2.环境变量的特性以及命令行操作

<1>命令行操作:

echo:打印特定的环境变量

export:增加环境变量 export  变量名 = 变量内容

env:查看所有的环境变量

getenv接口:这个函数可以获得特定的环境变量,const char* p  =  getenv("环境变量名");如果获取成功,环境变量字符串的地址,如果失败,就返回NULL。单个环境变量可以用于身份识别。

environ 指针:这是一个二级指针,指向的也是env环境变量表,下面用一段代码来演示一下(使用时要用extern声明)

unset: 清除环境/本地变量。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(int argc, char* argv[],char* env[])
{
    extern char** environ;
    for(int i = 0; environ[i]; i++)
    {
        printf("environ[%d] -> %s\n",i,environ[i]);
    }
    return 0;
}

运行结果:

<2>特性:

其实我们的main函数,还有一个参数 char* env[] ,这个就是环境变量,我们可以用一段代码来验证一下。

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就是环境变量,env本身和argv这个数组几乎是一样的,只不过存的东西不同,形式是一样,都以NULL结尾,每个元素存一个环境变量字符串。而这里环境变量被作为参数传递给了main函数,那么是谁传递给main的呢?答案是该进程的父进程,也就是bash。bash进程本身是由一张环境变量表的,创建子进程后,它会把自己的环境变量表env,传个子进程,也就是说环境变量是可以被子进程继承下去的。这里我们可以用一段代码来验证一下。

int main(int argc, char* argv[],char* env[])
{
    printf("I am a process , pid: %d, ppid:%d\n",getpid(),getppid());
    for(int i = 0; env[i]; i++)
    {
        printf("---------------env[%d] : %s\n",i,env[i]);
    }
    pid_t id = fork();
    if(id == 0)
    {
        printf("——-------------------------\n");
        printf("I am a child , pid: %d, ppid:%d\n",getpid(),getppid());
        for(int i = 0; env[i]; i++)
        {
            printf("---------------env[%d] : %s\n",i,env[i]);
        }
    }
    sleep(1);
}

运行结果

这里我们可以看到,子进程也能打印出环境变量,所以我们也可以得出环境变量有全局性。

三、本地变量

除了环境变量,还存在本地变量,我们只需要将 “ 变量名 = 变量内容” 输入命令行即可,再用echo $变量名 ,就能查看本地变量。env是无法看到本地变量的。当然,你也可以使用set命令,这个命令会打印出所有的变量,包括本地变量和环境变量。需要注意的是,本地变量只在bash内部有效,也就是说,本地变量是不能被子进程所继承下去的。

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值