Linux环境变量,进程地址空间

本文详细介绍了环境变量在操作系统中的作用,如PATH、HOME和SHELL等,展示了如何查看、设置和获取环境变量,以及环境变量的全局性和进程地址空间的关系。通过示例说明环境变量在父子进程间的继承和虚拟地址的概念。
摘要由CSDN通过智能技术生成

环境变量

1.概念

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

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

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

思考:为什么Linux下的命令行指令可以直接执行,不需要带路径,而我们写的二进制程序 需要带路径才能执行?

答案:是因为这些命令的路径已经添加在系统环境变量中了。

2.常见的环境变量

PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash。

3.查看环境变量的方法

echo $NAME //NAME:你的环境变量名称

4.相关的命令

echo:显示某个环境变量的值。

export:设置一个新的环境变量。

env:显示所有环境变量。

unset:清除环境变量。

set:显示本地定义的shell变量和环境变量。

5.环境变量的组织方式

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

6.通过代码获取环境变量

通过命令行第三个参数获取

#include<stdio.h>

int main(int argc,char *argv[],char*env[])
{
    for(int i=0;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;
}

lib中定义的全局变量environ 指向环境变量表,environ没有包含在任何头文件中,所以使用的时候需要 extern声明。

7.通过系统调用获取,设置环境变量。

#include <stdio.h>
#include <stdlib.h>
int main()
{
    printf("%s\n", getenv("PATH"));
    return 0;
}

8.环境变量的全局属性

环境变量通常具有全局属性,可以被子进程继承下去

进程地址空间

32位平台

先给出一个概念,上面程序的地址空间,实际为虚拟地址空间。 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{
    pid_t id = fork();
    if(id < 0){
            perror("fork");
            return 0;
        }
    else if(id == 0){ //child
            printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
        }
    else{ //parent
            printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
        }
    sleep(1);
    return 0;
}

我们发现,输出出来的变量值和地址是一模一样的,很好理解呀,因为子进程按照父进程为模版,父子并没有对变量进行进行任何修改。可是将代码稍加改动:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main()
{
    pid_t id = fork();
    if(id < 0){
        perror("fork");
        return 0;
    }
    else if(id == 0)
    {
         //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取
        g_val=100;
        printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    else
    { //parent
        sleep(3);
        printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
    }
    sleep(1);
    return 0;
}

可以发现此时父子进程中的 g_val输出不一致了,但是地址确还是一样。

可以得到以下结论。

变量内容不一样,所以父子进程输出的变量绝对不是同一个变量。

但地址值是一样的,说明,该地址绝对不是物理地址!
在Linux地址下,这种地址叫做虚拟地址
我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理,OS负责将虚拟地址转化成物理地址。

看上图,每个进程都有自己独立的进程地址空间(虚拟地址空间),一个进程包含数据和代码两部分,其中数据几位 task_struct的进程数据结构管理,通过一个指针 指向进程地址空间,进程在编译好,运行之前其内部已经包含地址,此地址为虚拟地址,通过页表映射的方式,在物理地址中开辟空间。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值