【Linux篇】细品环境变量与地址空间

基本概念

  • 环境变量(environmentvariables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数

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

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

举例理解

在编写c/c++代码时,main函数我们称为"我们自己的程序入口",但main函数其实也是被其他函数调用的,在linux系统下是被一个叫statr()的函数调用。同时,main函数也是有参数的。

  • argv[]:是一个指针数组,指向传入的字符串

  • agrc:表示子字符串个数

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

将代码改写成以下形式放到linux下运行,得到以下结果

复制代码
#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;
}

这与我们在linux下输入的指令类似,如:

  • ls -a

  • ls -l

原因

这是因为我们输入的./code -a -b -c会先被bash获得,然后被拆分成一个一个的字符串,将他保存到argv[0...i]中去。在Linux中,我们输入的命令如"ls -a"会先被bash获得,然后被bash拆分成一个一个的字符串。这样,我们就能通过命令行参数实现一个个子功能了,就好比"ls -a","ls -l"这般

main的命令行参数,是实现程序不同子功能的方法:也是指令选项实现的原理

复制代码
 #include<stdio.h>
  2 #include<string.h>
  3 int main(int argc,char*argv[])
  4 {
  5     if(argc!=2)
  6     {
  7         printf("Usage:./code [-a|-b|-c]\n");
  8         return 1;
  9     }
 10     const char*arg=argv[1];
 11     if(strcmp(arg,"-a")==0)
 12     {
 13         printf("这是功能1\n");
 14     }
 15     else if(strcmp(arg,"-b")==0)
 16     {
 17         printf("这是功能2\n");
 18     }
 19     else if(strcmp(arg,"-c")==0)
 20     {
 21         printf("这是功能3\n");
 22     }                                                                                                                                                                                                                            
 23     else
 24     {
 25         printf("Usage:./code [-a|-b|-c]\n");
 26     }
 27    // for(int i=0;i<argc;i++)
 28    // {
 29    //     printf("argv[%d]:%s\n",i,argv[i]);
 30    // }
 31     return 0;
 32 }

由此我们可以得出,进程是有一张表的,argv表,用来支持实现选项功能

执行一个命令先需要先找到它。

我们使用的指令其实就是二进制程序,与上面所实现的"code"其实没有区别。

那为什么使用指令时可以不用带路径?

  • 系统中存在环境变量,来帮助系统找到对应的指令,即二进制文件

  • 若把上面我们实现的"code"拷贝到usr/bin/路径下,就不用带路劲了

为什么将二进制文件放到usr/bin/路径下系统就能找到呢?

  • 因为系统中存在环境变量(PATH),环境变量会标识一段路径,环境变量告诉系统到哪些路径下查找二进制文件

查看环境变量:env

  • 环境变量的构成:名称=内容

  • 标识环境变量的唯一性是用名称来标识的

  • 表示环境变量的唯一性是靠名称

获得环境变量的内容

  • echo $PATH

shell查找指令就是从环境变量的路径中去查找。以":"为分隔符,将路径一个一个取下来,然后添加到指令前,若存在该指令则执行,否则就报错command not found。

比如查找"ls"指令:

复制代码
//将路径取下来添加到指令前
/usr/local/bin/ls//若没找到,则继续向下一个路径中查找
/usr/bin/ls//若找到,则执行指令

添加环境变量:

复制代码
//第一种
PTAH=$PATH:+要添加的环境变量内容
//这种方式添加环境变量,不会覆盖原来环境变量的内容
复制代码
//第二种
PATH=要添加的环境变量内容
//这种方法会覆盖原有内容

想要恢复初始的PATH内容,直接重启服务器就行

如何理解环境变量?

存储角度 :在用户登录的时候,会分配一个bash,bash会在自身内部形成一张表 ,即"环境变量表",当用户输入命令时,bash会先得到这串命令,然后分割形成一张命令行参数表 ,再拿着命令(如ls)在环境变量表中找到PATH,将PATH中保存的路径一 一添加到命令前查找命令,找到就执行,没找到就告诉系统"command not found"。所以在bash内部会有两张表:命令行参数表,环境变量表(也就是一个指针数组char*[])。

环境变量表

环境变量表就类似c++中学的键值对。

在bash启动的时候,它会为环境变量表new、malloc一段空间,同时还会new、malloc一段空间用来存放环境变量内容组成的常字符串。

所以环境变量到底是什么?
就是k、value的常字符串

所以环境变量是保存在bash进程自己的上下文中

环境变量最开始是从哪来的呢?

  • 系统相关的配置文件

系统给每个用户的家目录下存放了两个隐藏文件,如下。

也就是说,在用户登录的时候,bash会读取以下文件,然后给用户配置环境变量

所以环境变量表的本质:是操作系统在自己配置文件中提供的。
所以它叫做:系统中,用来指定系统运行环境的一些参数,而这些参数未来是被bash使用的,bash使用了,说明用户间接的使用了

所以,执行命令要先找到它,找的任务是由bash自己执行的。

比如:"cd ~"为什么能返回到家目录?

因为bash的环境变量表中存放了一个环境变量叫"HOME",在用户登录的时候bash会把用户当前的路径保存HOME中。也就是HOME=/home/用户名。将cd命令在环境变量表中查找,找到后,再将参数"~"也传过去,bash接收到命令后,便开始执行命令。所以cd ~能返回家目录

认识更多环境变量

记录历史命令的环境变量

最多记录一千条历史命令

记录当前主机的名的环境变量
记录当前工作路径的环境变量
记录上一次路径
记录当前登录的用户

获取环境变量的方法

操作
  • export:导入环境变量

  • env:查看环境变量

  • echo $XXX:查看单个环境变量

  • unset:取消环境变量

代码方式
关于main函数

main函数也是被其他函数调用的,linux下是_start(),在代码编译的时候编译器会扫描main函数带了几个参数,然后根据参数量进行调用main函数

方法一:
复制代码
//获取的是父进程的环境变量
//同时,父进程的环境变量也可以被孙子进程、曾孙..继承
//说明环境变量是一个具有全局属性变量
export MYPATHY1=111
export MYPATHY2=222
export MYPATHY3=333

#include<stdio.h>
#include<string.h>
int main(int argc,char*argv[],char*env[])
{
    (void)argc;
    (void)argv;
   
    for(int i=0;env[i];i++)
    {
       printf("env[%d]->%s\n",i,env[i]);                                        }
方法二:
复制代码
//getenv根据环境变量名查找环境变量,返回环境变量的指针 

#include<stdio.h>
 #include<stdlib.h>//getenv函数的头文件
 #include<string.h>
 int main(int argc,char*argv[],char*env[])
 {
    (void)argc;
     (void)argv;
    (void)env;

    char*path=getenv("PATH");
    if(path==NULL)return 1;                                                 printf("PATH->%s\n",path);

  return 0;
}
--------------------------------------------
//写一个只有自己能执行的程序
#include<stdio.h>
#include<string.h>
int main(int argc,char*argv[],char*env[])
{
    (void)argc;
    (void)argv;
     (void) env;
    char*who=getenv("USER");
  if(strcmp(who,"xiaohao")!=0)
  {
    printf("Only xiaohao\n");
    return 1;
  }
    printf("这是正常的执行逻辑\n");
  return 0;
}
/*
  
  
*/

为什么要让父进程的子进程、孙进程....继承自己的环境变量

子进程继承了环境变量,就能执行一些个性化操作,比如定制一个只能自己执行的程序

方法三:
复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>//environ的头文件

extern char**environ;//使用前需要先声明

int main(int argc,char*argv[])
{
     (void)argc;                                                          (void)argv;
 
     for(int i=0;environ[i];i++)
     {
         printf("env[%d]->%s\n",i,environ[i]);
     }
  return 0;
}
//char**environ是指向环境变量表的一个二级指针

环境变量的特性

  • 环境变量具有全局特性
补充两个概念
  • bash允许用户定义本地变量,且不会被子进程继承,只允许在bash内部使用

    复制代码
    //设置本地变量
    [xiaohao@iZ2zeebi0w2dzgbbqlrmxgZ 12-31]$ i=10
    //查看本地变量
    [xiaohao@iZ2zeebi0w2dzgbbqlrmxgZ 12-31]$ set  
    //查看单个本地变量
    [xiaohao@iZ2zeebi0w2dzgbbqlrmxgZ 12-31]$ echo $i
    //取消本地变量
    [xiaohao@iZ2zeebi0w2dzgbbqlrmxgZ 12-31]$ unset

环境变量是在谁里面?

  • bash
  • 既然在bash里面,为什么export导环境变量能导到bash里?命令执行后不都是bash的子进程吗?
  • 因为执行export不需要创建子进程,而是bash自己执行。bash自己调用函数或者系统调用完成。export是内建命令----built-in command
相关推荐
緈福的街口几秒前
【leetcode】125.验证回文串
linux·算法·leetcode
德先生&赛先生16 分钟前
深入理解c语言中的static
c++
Invinciblenuonuo18 分钟前
Linux【5】-----编译和烧写Linux系统镜像(RK3568)
linux·操作系统·rk3568·系统编译
T0uken33 分钟前
【Linux】HAProxy:结合 WG 实现内网 TCP 反代
linux·运维·tcp/ip
鸢时望巧35 分钟前
Shell循环(二)
运维·开发语言
景彡先生42 分钟前
C++ 中的 iostream 库:cin/cout 基本用法
开发语言·c++
wanhengidc1 小时前
大数据服务器和普通服务器之间的区别
大数据·运维·服务器
网硕互联的小客服1 小时前
如何诊断服务器硬盘故障?出现硬盘故障如何处理比较好?
大数据·运维·服务器
vortex51 小时前
Linux Shell 中的 dash 符号 “-”
linux·运维·服务器
月堂1 小时前
Linux操作系统-性能优化
linux·运维·服务器