• 进程的环境变量


    有OS时,进程从启动到正常终止的全过程

    • exit():加载器

    • 启动代码也是调用exit()来终止函数

    • 终止处理函数是exit()退出时,优先调用的,等终止处理函数结束时,调用_exit()

    _exit正常退出时,不会调用进程终止处理函数

    有关标准IO的库缓存的缓冲有三种,无缓冲行缓冲全缓冲

    就是调用文件IO的情况:

    • 无缓冲就是一调用就输出;行缓冲是满了一行才输出;全缓冲是全部缓冲区积满才输出

    标准IO是基于系统函数文件IO的封装库

    为什么调用exit正常终止时,会刷新标准io的缓存呢?

    因为exit会调用fclose关闭所有的标准io,关闭时会自动调用fflush来刷新数据。

    命令行参数

    在命令行执行c程序时,可以输入命令行参数并传递给main函数的形参,然后进程就得到了命令行的参数。

    其中./可执行文件是命令行参数,其后跟的参数叫程序参数,也是命令行参数

    #include
    int main(int argc,char** argv){
     int i=0;
     for(;i<argc;i++){//argc:参数个数
         printf("%s\t",argv[i]);
     }
     printf("\n");
     int j=0;
     for(;argv[j]!=NULL;j++){//argv:二级指针,每一级指向一个数组
         printf("%s\t",argv[j]);
     }
     return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    //执行结果
    ./main aaa bbb ccc
    ./main  aaa     bbb     ccc   
    ./main  aaa     bbb     ccc    
    
    • 1
    • 2
    • 3
    • 4
    命令行参数传递给main函数过程
    						构建指针数组                  exec
    ./a.out *** *** ——————> 终端窗口进程 ——————> OS 内核 ——————> 启动代码 ——————> main函数形参
    
    • 1
    • 2

    环境变量表

    1. windows
      • 在windows下,如果你不加路径的话,会道默认到当前路径下找程序,没有的话就找不到你的程序
      • 只要把程序所在路径,加入windows的path环境变量,加入后,随便在什么位置,都可以不加路径的执行这个程序

    path这个环境变量的作用:专门记录各种可执行程序所在路径

    path记录后:

    1)如果你有明确指定路径,那就直接到你指定的路径下找到程序并执行

    2)如果没有明确指定路径,首先,在当前目录下找,如果不到这个程序,就会跑到path记录的各个路径下面去找

    ​ 通过图形界面,双击快捷图标来打开程序的话,快捷图标可以自动找到所指向的程序并执行,所以对于图形界面这种操作方式来说,path的意义不是很大

    windows环境变量
    1. 环境变量的组成:环境变量 = 环境变量名 + 环境变量数据

    自己创建一个环境变量:

    先在用户变量新建一个:环境变量名+值(一般是路径)

    ***%环境变量名%*代表的就是该“环境变量”的数据,%%**就是用来获取环境变量数据(值)

    环境变量被存放在了“环境变量表”里面,最原始的“环境变量表”都被保存在了“环境变量文件”中

    什么是环境变量

    ​ 其实就是进程在运行时,会用到的一些字符串信息,环境表就好比是工具箱,里面放了各种进程运行时需要用到的“工具”,比如各种的路径

    通过图形界面设置、修改windows“环境变量”时,修改、设置的内容,都会被永久保存到“环境变量文件”中

    每个进程的环境变量表:
    每一个进程都在自己的内存空间(堆空间)保存了一份自己的环境变量表。
    
    • 1
    • 2

    如果某环境变量的数据有很多条,在环境变量

    • 在windows这边使用;分隔
    • Linux这边则使用:分隔
    • 在命令行执行自己的程序时,查找的是“命令行窗口进程”的“环境变量表”

    • 为什么只有重新打开“命令行窗口”后, 新设置的“环境变量”才生效?

      因为新设置的环境变量,只是被保存到了windows的环境变量文件中,但是之前所打开的“命令行窗口”进程的“环境变量表”还没有得到更新,只有当重新打开后,才能更新。
      其实在w10以前更麻烦,更新了环境变量文件后,必须要重启系统才能生效,不过w10后不用这么麻烦了,只需要重新打开即可。


    Linux系统变量

    永久修改

    基本都是通过修改“环境变量文件”来实现的

    临时修改
    • 就是只修改当前进程自己的“环境变量表”

    • 其它不相关进程的“环境变量表”以及“环境变量文件”中数据,不会发生任何变化

    • 当进程结束时,当前进程的“环境变量表”就被释放了

      ---------这就是临时修改

    如何实现临时修改

    1. 使用命令修改------改的是“命令行窗口进程”的环境变量表
    2. 通过API修改------修改的只是我自己程序的“环境变量表”

    查看所有环境变量

    • Linux

    命令:export

    把当前“终端窗口进程”的所有环境变量全部显示出来

    • windows

      命令:set

    把当前“终端窗口进程”的所有环境变量全部显示出来

    显示单个的环境变量

    • Linux

    ​ 用法:echo $环境变量命令

    PATH是环境变量名,$PATH代表的就是PATH的环境变量数据,可以认为$就是用来获取环境变量数据的

    在Linux,环境变量的多个数据之间使用:分隔

    • windows

    ​ 用法:set 环境变量名 或者 set %环境变量名%

    添加一个新的环境变量
    1. Linux

      例子:export AA=wwwwwwwwwwww

      • 新环境变量名叫AA
      • 环境数据为wwwwwwwwwwww

      在Linux下,环境变量名往往喜欢一律大写

    2. windows

    例子:set aa=wwwwwwwwwwww

    修改已有的环境变量
    1. 覆盖修改

      ​ 覆盖原有数据,还是使用添加新环境变量的命令来操作,如果添加的“环境变量”之前就存在了,现在的数据会修改原来的数据

      Linux
      export AA=sssssssssss

    2. 末尾追加

      保留原有数据

      1. windows
      • set aa=%AA%;dddddddddddd
      • set aa=dddddddddddd;%AA%
      1. Linux

      添加后只用:可执行文件名即可执行,无需./

      export AA= A A : d d d d d d d d d d d d 或者 e x p o r t A A = d d d d d d d d d d d d : AA:dddddddddddd 或者 export AA=dddddddddddd: AA:dddddddddddd或者exportAA=dddddddddddd:AA
      //$AA就表示原来的数据,新写的数据用:分割

    删除环境变量

    1.Linux unset AA

    2.windows set aa=

    ​ 不管是在windows下还是在Linux下,在命令行下添加/修改环境变量时,改动的只是当前“命令行窗口进程”的环境变量表

    • 当你在另一个窗口查看时,根本找不到这个修改
    • 当你把当前窗口关闭后,当前“命令行窗口进程”的环境变量表也就被释放了,那么之前的修改自然也就无效了

    通过API修改环境变量表

    1. 获取环境表中的所有环境变量

    environ全局变量

    • char** environ
    • 指向的是一个字符串指针数组------------每一行就是环境变量字符串
    #include
    #include
    //声明变量:environ
    extern char** environ;
    int main(int argc,char** argv){
        int i=0;
        for(;environ[i]!=NULL;i++)
             printf("%s\n",environ[i]);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //main函数的第三个参数
    #include
    #include
    int main(int argc,char** argv,char** environ){
        int i=0;
        for(;environ[i]!=NULL;i++)
             printf("%s\n",environ[i]);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1. 调用API:实现环境变量的添加、修改等
    putenv、setenv:添加和修改环境变量
    #include 
    /*
    设置新的环境变量到环境表中:
         如果这环境变量之前就存在,那么这一次的数据会无条件覆盖之前的数据
         如果不存在,就添加这个新的环境变量
    */
    //string:新的环境变量,比如“name=value”
    int putenv(char *string);
    /*
    	name:环境变量的名字。
    	value:环境变量值。
    	overwrite:如果发现name环境变量以前就已经存在,会根据overwrite的值来决定是否覆盖,
    				0:不覆盖;0:覆盖
    */
    int setenv(const char *name, const char *value, int overwrite);
    //tenv函数:调用成功返回0,失败返回非0,errno被设置。
    //tenv函数:调用成功返回0,失败返回-1,errno被设置
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    #include
    #include
    extern char** environ;
    int main(int argc,char** argv){
        int i=0;
        putenv("aaa=wwwwwww");
        setenv("bbb","nnnnnnnn",0);
        for(;environ[i]!=NULL;i++)
            printf("%s\n",environ[i]);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zuzXcrbL-1667817527423)(/home/guojiawei/.config/Typora/typora-user-images/image-20221107181828223.png)]

    注意想查看到结果,不可以采用第三个参数,只可以使用extern声明

    unsetenv
    #include 
    //删除环境变量函数
    //删除name指定名字的环境变量
    int unsetenv(const char *name);
    
    • 1
    • 2
    • 3
    • 4
    #include
    #include
    extern char** environ;
    int main(int argc,char** argv){
        int i=0;
        putenv("aaa=wwwwwww");
        putenv("aaa=www");
        setenv("bbb","nnnnnnnn",0);
        unsetenv("bbb");
        for(;environ[i]!=NULL;i++)
            printf("%s\n",environ[i]);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    getenv
    #include 
    
    char *getenv(const char *name);
    
    • 1
    • 2
    • 3
    int main(int argc,char** argv){
        char* p=getenv("PATH");
        printf("PATH=%s\n",p);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    自己所写程序的环境表是怎么来的

    命令行窗口执行./a.out,那么a.out进程就属于“命令行窗口进程”的子进程,子进程的环境表是从父进程复制得到的

    • 当有OS支持时,基本所有的进程都是由父进程“生”出来的
    	原始进程————>进程————————>进程————————>终端进程——————>a.out进程
    				|            |             |
    				|            |             |
    				V            V             |
    			   进程		   进程          进程
    				|            |             |
    				|			 |             |
    			   ...		    ...           ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 所有进程的“环境变量表”都是从父进程复制得到的
    • 最原始进程的“环境变量表”则是从“环境变量文件”中读到的
      原始进程           子进程	         子进程			 子进程			
     环境变量文件 ————> 进程环境表 ————————>进程环境表 ————————>进程环境表 ————————>.....
    
    • 1
    • 2
    • 自己的进程有一个子进程的话,也会继承自己进程的环境表

    c程序空间布局

    1. 什么是c程序的内存空间

      c程序运行时,是运行在内存上的,也就是说需要在内存上开辟出一块空间给c程序,然后将C代码会被从硬盘拷贝到内存空间上运行

    2. c程序的内存空间结构

      这段空间必须布局为c程序运行所需的空间结构,c程序才能运行

      如果空间没有布局好,进程将无法运行,因此进程空间(c程序的内存空间)也是非常重要的进程环境

      c的内存结构是由启动代码来搭建的

      比如启动代码会把c内存空间的某一部分空间,构建为“栈”,也就是说以“栈”的方式来管理这片内存

    c程序代码在内存上运行起来后,它就是一个进程,所以程序代码在内存上所占用的空间,也别称为进程空间

  • 相关阅读:
    电子制造行业的数字化转型突破点在哪?精益制造是关键
    thinkPHP框架详解+部署
    Win10添加、删除鼠标右击的选项(快捷方法)
    模式分解的概念(下)-无损连接分解的与保持函数依赖分解的定义和判断、损失分解
    PNG 免抠素材网,设计师必备
    JAVASE事件监听
    java计算机毕业设计ssm+jsp计算机视频学习网站
    Toou-2D windows 打包部署
    [PyTorch][chapter 55][GAN- 3]
    (50)其他的性能测试场景
  • 原文地址:https://blog.csdn.net/weixin_47173597/article/details/127733612