进程环境变量

目录

1、环境变量的基本概念

2、常见环境变量

3、查看环境变量的方法 

4、测试PATH 

5、环境变量相关命令

6、环境变量的组织方式 

7、深入理解main函数里的三个参数

8、通过代码获得环境变量 

9、通过系统调用获取环境变量

10、环境变量通常是具有全局属性的 


1、环境变量的基本概念

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。

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

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

我们都知道我们自己写的一串代码,经过编译链接后可以生成可执行程序,我们用./即可使其运行,但是我们系统里的大部分命令也是64位的可执行程序:

  • 既然都是程序,那我们是不是也可以把自己写的程序叫做指令,或者说把系统里面的指令叫做命令程序或者是二进制程序呢??答案是是的!!!我们自己写的程序和系统中的指令并没有多大的区别,我们都可以将其称为指令、工具、可执行程序。

既然它们都一样,那为什么系统里的ls、pwd等命令可以直接用,但是自己写的程序process却要加上./才能运行?

  • command not found-指令无法找到。我们执行一个可执行程序,前提是要找到它!那么为什么系统的命令能找到,而我们自己的程序找不到呢?? 原因就在于linux系统中是存在相关的环境变量,保存了程序的搜索路径的!

2、常见环境变量

我们可以输入指令env查看所有的环境变量:

我们可以发现环境变量的形式都是:变量name+value 

常见的环境变量如下:

  • PATH:系统中搜索可执行程序(命令)的环境变量。
  • HOME:指定用户的家目录(即用户登陆到Linux系统中时,默认的目录)。
  • SHELL:当前Shell,它的值通常是/bin/bash。

下面我们来查看一下系统中的环境变量PATH:

3、查看环境变量的方法 

我们可以输入下面的指令来实现对环境变量的查看:

echo $MANE //NAME:所要查的环境变量的名称

我们以查看PATH环境变量为例:

🍒:注意这里的路径分隔符是用:间隔的,当我们输入ls指令时,系统会在这些路径里面一个一个寻找,找到了就执行特定路径下的ls。 这也就证实了一开始所说的,因为我们写的程序不在此路径里面,自然就不能直接用。 

4、测试PATH 

首先我们创建一个可执行文件process:

我们知道我们创建的可执行文件process不能像系统的命令那样直接使用

如果我们想要使自己写的文件process像系统中的命令一样能够直接使用,我们可以使用以下两种方法:

  • 手动添加到系统的路径/usr/bin/里面。
  • 使用export命令把process当前所在的路径也添加到PATH环境变量里面。

1、手动添加到系统路径/usr/bin/里面:

⚠: 并不建议把自己写的可执行程序随意添加到系统里面,这样会造成系统污染,所以我们执行下面命令将其删除:

2、使用export命令把process当前所在的路径也添加到PATH环境变量里面:

我们不仅仅只能在代码中定义变量,我们在linux的命令行中也可以定义变量,命令行中的变量也具有临时属性,当我们将xshell窗口关掉重新打开后,其环境变量还是以前未被修改过的环境变量。linux命令行中的变量分为两种:

  • 1.本地变量
  • 2.环境变量(具有全局属性

如果我们在变量前面加上export,这就是导出环境变量:

如果我们想要删除这个环境变量,我们执行unset命令:

下面演示如何将process的路径导入PATH里面,我们输入如下命令:

export PATH=$PATH:/junpeng/linux-code/day1

这条命令的意思是把所有的PATH环境变量的内容提取出来放到PATH里头,并且在后面追加process的当前路径。往后就可以像命令一样直接使用process了。

5、环境变量相关命令

  • echo: 显示某个环境变量值。
  • export: 设置一个新的环境变量。
  • env: 显示所有环境变量。
  • unset: 清除环境变量。
  • set: 显示本地定义的shell变量和环境变量。

前面四个命令我们都讲到过,唯独set还没有讲,下面我们来看一下set命令:

我们使用export可以导出环境变量,使用env查看环境变量:

不加export定义的就是本地变量,我们可以通过set命令查看本地变量,也可以查看环境变量:

6、环境变量的组织方式 

每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串。

7、深入理解main函数里的三个参数

我们前面获取环境变量的方式都是通过命令行的方式,下面我将通过代码程序来演示如何获取环境变量。

在讲用代码程序获取环境变量前我们先深入了解一下main函数。

问:main函数可以带参数吗?最多可以带多少个?

答:main函数有三个参数,只不过我们平常不怎么用,因为涉及系统层面。所以也就没怎么见过。

int main(int argc, char* argv[], char* envp[])
{
	return 0;
}
  • int argc:数组里面元素个数。
  • char* argv[ ]、char* envp[ ]:指针数组。

下面我们先谈它的前两个参数,我们先来一段代码用作测试用例:

 运行结果如下:

  • main函数的第二个参数是一个字符指针数组,此数组的下标0的位置存储的是你命令行的第一个位置(可执行程序),所以这里是第一行为:argv[0]:./myproc。其余的字符指针存储的是命令行对应的选项,所以会出现argv[1]:-a……,而main函数里的第一个参数存储的是数组里的元素个数。

⭐:我们给main函数传递的argc,char* argv[ ]是命令行参数,传递的内容是命令行中输入的程序名和选项,并且结尾以NULL结束。

问:main函数传这些参数的意义是什么?

假如我们现在要实现一个命令行计算器,如果我们往命令行输入:./myproc -a 10 20,那么就代表加法:10+20=30,如果输入:./myproc -s 10 20,那么就是减法10-20=-10.........代码如下:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
	if (argc != 4)
	{
		printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
		return 0;
	}
	int x = atoi(argv[2]);
	int y = atoi(argv[3]);
	if (strcmp("-a", argv[1]) == 0)
	{
		printf("%d+%d=%d\n", x, y, x + y);
	}
	else if (strcmp("-s", argv[1]) == 0)
	{
		printf("%d-%d=%d\n", x, y, x - y);
	}
	else if (strcmp("-m", argv[1]) == 0)
	{
		printf("%d*%d=%d\n", x, y, x * y);
	}
	else if (strcmp("-d", argv[1]) == 0 && y != 0)
	{
		printf("%d/%d=%d\n", x, y, x / y);
	}
	else
	{
		printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
	}
	return 0;
}

此时我们就可以运行此程序并通过命令行参数来实现我们想要的计算方式:

  • 综上:同一个程序,通过传递不同的参数,让同一个程序有不同的执行逻辑,执行结果。Linux系统中会根据不同的选项,让不同的命令可以有不同的表现,这就是指令中各个选项的由来和起作用的方式!!这也就是命令行参数的意义,同样也就是main函数参数的意义。 

下面我们来谈一下main函数的第三个参数

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

char*envp就是环境变量。也是一个字符指针数组,前面的argv是指向的命令行参数字符串,而这里envp指向的是一个一个环境变量字符串,最后也是以NULL结尾。结构图如下:

我们可以用如下代码来测试第三个参数:

 运行后:

总结:一个进程是会被传入环境变量参数的。 同时一个函数在声明和定义的时候都没有参数,那么我实际传参的时候可以传参。

8、通过代码获得环境变量 

在前面我们得知main函数的第三个参数可以获取环境变量:

我们也可以通过第三方变量environ获取:

 

9、通过系统调用获取环境变量

  • 除了通过main函数的第三个参数和第三方变量environ来获取环境变量外,我们还可以通过系统调用getenv函数来获取环境变量。

 ⭐:getenv可以通过目标环境变量名进行查找,返回一个对应的字符指针,从而直接获得环境变量的内容。

 问:为什么要获得环境变量?

  • 假设我们当前的用户USER为zhangsan,但是我只允许自己使用,不允许其它人访问,就可以用获得环境变量来解决:

以上只是环境变量的一个用途,还有许多用途需要我们慢慢发掘。 

10、环境变量通常是具有全局属性的 

我们首先来回顾一下bash进程:

  • 我们知道我们每次运行进程,子进程的pid总是不断发生变化的,因为每次运行进程都需要重启,但是父进程却是不变的,因为父进程就是bash,是系统创建的命令行解释器。

  • 如果我们把bash进程杀掉,那么我们输入任何命令都不会有反应了,命令行直接挂掉。我们之所以能够正常使用命令行,原因就在于这些命令本身就是被bash进程获得。而这个bash进程就是在我们登录系统时,系统自动帮我们创建的,在命令行中启动的进程,其父进程都为bash。 

下面我们来理解一下环境变量具有全局属性

  • 我们看如下代码:

  • 运行此代码:

  •  通过运行结果我们可以看到:我们的进程刚开始并不存在环境变量,但如果我们自己导出一个环境变量,我们再运行看看:

✍🏻结论: 

  • 环境变量是会被子进程继承下去的!!类比于从bash进程开始,往后创建一大批的子进程,若在bash进程的位置就创建了export环境变量,那么此环境变量就会从定义处bash位置开始被所有的子进程拿到。所以环境变量具有全局属性!!!
  • 而本地变量之所以在本地有效,是因为本地变量是在bash内部定义的变量,不会被子进程继承下去!!!​

🤔我们看接下来的一个问题:

  • 这里local_val是一个本地变量,命令行中启动的所有程序都要创建子进程,echo也是一个命令、一个子进程, 父进程bash内定义的local_val变量怎么能被子进程读到呢?不是说本地变量不会被子进程读到吗?后面为何能用echo打出hello呢?

⭐:linux下大部分的命令是通过子进程的方式执行的。但是还有一部分命令不是通过子进程的方式执行。而是由bash自己执行(调用自己所对应的函数来完成特定的功能),我们把这种命令叫做内建命令

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值