🎁个人主页:我们的五年
🔍系列专栏:Linux课程学习
🌷追光的人,终会万丈光芒
🎉欢迎大家点赞👍评论📝收藏⭐文章
目录
HOME环境变量:
PWD环境变量:
USER和LOGNAME环境变量:
让我们的程序,指定某个用户运行:
su命令和su - 命令:
获得环境变量:
其他环境变量:
定义一个全局变量(shell维护的变量):
理解env,argv和export:
让子进程不被启动:
为什么子进程要继承父进程的环境变量?
获取环境变量的方式:
1.是先到家目录,然后再加载环境变量中的HOME?还是现有环境变量HOME,在根据这个到指定的目录呢?
是有环境变量HOME,环境变量先被加载。然后才能让工作路径到HOME目录。
2.bash也是一个进程,它的环境变量是根据用户和系统的配置文件来的。
3.所有的进程都是-bash的子进程。这些子进程的环境变量是从bash中拷贝的。
4.识别用户身份,不同的用户运行一个程序,不同用户的USER和LOGNAME是不同的,getenv又可以拿到这些环境变量,所以可以让哪些用户可以运行这个程序。
5.环境变量VS本地变量?
6.当创建一个子进程时,子进程会继承父进程的环境变量,这包括了操作系统级的环境变量,还有父进程设置的环境变量。
本地环境变量,默认不会传递给子进程。
子进程会继承父继承的环境变量。
7.为什么环境变量具有全局性?
因为子进程都会进程父进程的环境变量,所以子进程都能看到这些环境变量,也能进行操作。也可以传递给自己的子进程,让自己的子进程看到。
8.为什么要让子进程继承父进程的环境变量?
HOME环境变量:
表示当前用户的家目录,cd ~就是回到这样的目录。
刚刚登录shell的目录,就是该用户的家目录。
PWD环境变量:
当前进程的所在的工作路径。
USER和LOGNAME环境变量:
表示当前的用户。一般相同。
当我们用普通用户进行su切换到root时,没有真正登录root,所以USER和LOSNAME还是原来的普通用户。没有加载环境目标用户的环境变量,所以SUER和LOGNAME没有变化。
所以我们以后区分一个程序,就只要关注这两个环境变量就可以了。
让我们的程序,指定某个用户运行:
下面代码在root和kym用户下执行的结构如下:
要运行一个程序,就是操作系统要为这个程序开一个进程。我们这些进程全部都是-bash的子进程。当新建一个进程时,会继承父进程的环境变量。root用户进行登录shell和kym进行登录的环境变量USER和LOGNAME是不一样和。所以我们在getenv("USER")的时候,拿到的是不一样的字符串。所以执行就会发生区别。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
if(strcmp(getenv("USER"),"kym")==0)
{
printf("用户为kym,执行成功!\n");
}
else
{
printf("用户不匹配,请用kym用户进行执行!\n");
}
return 0;
}
su命令和su - 命令:
su命令:
如果不指定用户名,那么默认切换到超级用户(root)。如果指定了用户名,那么就切换到指定的用户。不管切换到那个用户,都不会加载该用户的环境变量,和启动该用户的脚本。
su - 命令:
会启动目标用户的脚本和加载环境变量。
获得环境变量:
头文件:
#include <stdlib.h>
函数原型:
char *getenv(const char *name);
进程可以通过系统调用获得当前的工作路径,后面新建文件就直接可以getenv("PWD")新建就行。
比如通过getenv获取PATH环境变量。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char* s=getenv("PATH");
printf("%s\n",s);
return 0;
}
其他环境变量:
LANG:UTF -8 表示语言是万国码,在不同的语言不会出现乱码。
LODPWD:最近一个路径。
所以cd - 的原理就是去环境变量中拿OLDPWD,就可以让路径切换回去。
cd -:返回最近一个路径。
定义一个全局变量(shell维护的变量):
他们不属于环境变量,通过env查看环境变量的时候,没有发现i=10,这个环境变量。
有shell内部进行维护。
set:显式本地的shell变量和环境变量。
unset (变量名):清除所有shell维护的环境变量。
export:将我们上面定义的全局变量,导入到环境变量中。
i=10;
set
理解env,argv和export:
每启动一个shell,操作系统就会启动一个-bash进程。开辟一块空间,存放一系列东西,里面包含了环境变量env,还有命令行参数列表,还有本地的环境变量。我们定义一个全局变量,比如i=10。其实就是在本地变量表中,有一个值存着"i=10"这个字符串起始位置。
export的效果就是,让env表指向"i=10"字符串。
shell脚本:在shell命令行中衍生出来的一种语言。因为命令行可以定义变量,识别for等一系列关键词。
让子进程不被启动:
运行一个程序,就是让-bash帮我们创建一个子进程。但是子进程不会继承父进程的本地变量,只会继承父进程的环境变量。所以我们在父进程设置一个变量,就能控制该程序能不能运行。
可以设置为要有这个环境变量才能运行,也可以设置没有这个环境变量才能运行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
char* is_running=getenv("ISRUNNING");
if(is_running==NULL)
{
while(1)
{
printf("程序被启动!\n");
sleep(1);
}
}
else
{
printf("程序启动失败!\n");
}
return 0;
}
这个程序就是:
1.没有ISRUNNING环境变量才能运行。
2.有ISRUNNING环境变量,getenv就返回NULL,打印"程序启动失败"
为什么子进程要继承父进程的环境变量?
a.系统的配置信息,尤其是具有指导性的配置信息。
我们给系统进行配置,就是让以后启动的任何进程都有这样的配置,而环境变量就是会把这些信息传递给以后的任何信息。而-bash的环境变量也是从bashrc和bash.profile文件中来的。所以在这些配置文件中配置一些信息,以后的进程都会有这些信息。
所以是配置信息生效的一种表现。
b.进程是具有独立性的
所以如果父进程有数据要传给子进程。普通的数据是不会传递给子进程的,我们就可以通过环境变量进行传递。(只读数据)
获取环境变量的方式:
1.mian函数的第三个参数。
2.通过getenv函数获取。
3.通过environ全局变量获取。
extern:声明
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern char** environ;
int main()
{
for(int i=0;environ[i];i++)
printf("env[%d]:%s\n",i,environ[i]);
return 0;
}