环境变量初识
环境变量解释起来比较抽象,先看示例:
#include <stdio.h>
#include <unistd.h>
#define NUM 100
#include <string.h>
int main()
{
char bar[NUM+1];
memset(bar,'\0',sizeof(bar));
const char* lable = "|/-\\";
int i = 0;
while(i <= 100)
{
printf("[%-101s][%%%3d](%c)\r",bar,i,lable[i%4]);//%% 输出一个%
fflush(stdout);
bar[i] = '=';
bar[i+1] = '>';
i++;
usleep(50000);//单位是毫秒
}
printf("\n");
return 0;
}
上面是一个进度条小程序的代码,gcc print.c -o print 编译后想要运行它,需要输入 ./print,./代表当前目录下。但是有一个问题,为什么gcc pwd vim 这些不需要加./,这些命令程序的代码在哪?
答案是他们都存在环境变量中,通过 PATH(是一种环境变量)可以查看 :
也就是说,这些不需要加路径( ./ )就可以执行的指令,是因为他们的路径都拷贝到环境变量中了;那么回到上面的进度条小程序,把它的路径也拷贝到环境变量中,操作如下:
(上述把print的路径加入到环境变量,只在本次会话有效,关闭退出时就会清除)
或者在windows中桌面的快捷方式,也和环境变量有关
除了上述介绍的PATH,还有一些常见的环境变量如:
- HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
- SHELL : 当前Shell,它的值通常是/bin/bash
查看环境变量方法 :
- echo $NAME (NAME是你的环境变量名称)
有了上述介绍的示例再来看环境变量的概念会好理解一些了
环境变量的基本概念:
一般是指在操作系统中用来指定操作系统运行环境的一些参数
环境变量是具有特殊作用/特殊用途的变量;环境变量也是一种变量(变量名+内容),本质是OS在内存中/磁盘中开辟空间,用来保存系统相关数据的,所以也是系统自己给自己定义的变量;
获取环境变量的方法:
- 命令行第三个参数
#include <stdio.h>
int main(int argc, char *argv[], char *env[])
{
int i = 0;
for(; env[i]; i++)
{
printf("%s\n", env[i]);
}
return 0;
}
- 通过第三方变量environ获取
#include <stdio.h>
int main(int argc, char *argv[])
{
extern char** environ;
int i = 0;
for(; environ[i]; i++)
{
printf("%s\n", environ[i]);
}
return 0;
}
在没包相关头文件时,environ前要加extern
- getenv 通过系统调用获取环境变量
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%s\n", getenv("PATH"));
return 0;
}
实际应用中,常用getenv(和putenv)函数来访问特定的环境变量,前两种不推荐也不常用。
环境变量还具有全局性
比如用fork创建子进程时,PPID是他的父进程,而父进程的PPID是谁呢,答案是bash,bash是一种命令行解释器,一般命令行启动的进程,他们的父进程都是bash。
在我们登录Linux时,bash会从系统中读取环境变量,存在一个环境变量列表中(如上图),那我们在子进程中可以用环境变量吗?
请看如下代码:
当把MYENV导出为环境变量时,bash的环境变量列表就多了一个MYENV而 ./myproc执行的指令的进程是bash的子进程发现可以执行MYENV这个环境变量相关的操作;
说明子进程可以获取到父进程环境列表中的环境变量 ====> 子进程继承了bash的环境变量 , bash的所有子进程都可以看到bash环境列表中的环境变量,就如同用fork创建子进程,子进程继承父进程的代码和数据一样 是可以继承的
所以,bash的所有子进程都可以获取到bash的环境列表,也就是环境变量具有全局属性