进程的环境变量

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

  • exit():加载器

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

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

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

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

就是调用文件IO的情况:

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

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

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

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

命令行参数

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

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

#include<stdio.h>
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;
}
//执行结果
./main aaa bbb ccc
./main  aaa     bbb     ccc   
./main  aaa     bbb     ccc    
命令行参数传递给main函数过程
						构建指针数组                  exec
./a.out *** *** ——————> 终端窗口进程 ——————> OS 内核 ——————> 启动代码 ——————> main函数形参

环境变量表

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

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

path记录后:

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

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

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

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

自己创建一个环境变量:

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

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

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

什么是环境变量

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

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

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

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

  • 在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<stdio.h>
#include<stdlib.h>
//声明变量: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;
}
//main函数的第三个参数
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char** argv,char** environ){
    int i=0;
    for(;environ[i]!=NULL;i++)
         printf("%s\n",environ[i]);
    return 0;
}
  1. 调用API:实现环境变量的添加、修改等
putenv、setenv:添加和修改环境变量
#include <stdlib.h>
/*
设置新的环境变量到环境表中:
     如果这环境变量之前就存在,那么这一次的数据会无条件覆盖之前的数据
     如果不存在,就添加这个新的环境变量
*/
//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被设置
#include<stdio.h>
#include<stdlib.h>
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;
}

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

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

unsetenv
#include <stdlib.h>
//删除环境变量函数
//删除name指定名字的环境变量
int unsetenv(const char *name);
#include<stdio.h>
#include<stdlib.h>
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;
}
getenv
#include <stdlib.h>

char *getenv(const char *name);
int main(int argc,char** argv){
    char* p=getenv("PATH");
    printf("PATH=%s\n",p);
    return 0;
}
自己所写程序的环境表是怎么来的

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

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

c程序空间布局

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

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

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

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

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

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值