Linux环境变量与虚拟地址空间

1.环境变量

1)基本概念

a.环境变量一般是指在OS中用来指定OS运行环境的一些参数
b.当我们编写代码的时候,在执行链接的时候,我们不知道所连接的动态静态库在哪里,但是照样可以链接成功生成可执行程序,原因是相关环境变量帮助编译器进行查找。
c.环境变量在系统中通常具有全局特性
d.按照环境变量的生命周期来划分,Linux环境变量可分为两类:永久的(需要配置文件)以及临时的(使用export命令生命即可,变量在关闭shell时会失效)

2)常见环境变量

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

3)查看环境变量的方法

echo $环境变量名称

4)PATH的使用

我们使用makefile执行文件时,是./执行文件名,使用命令export PATH=$PATH:执行文件的路径,就将执行文件的路径放到环境变量PATH中,然后直接输入执行文件名,便可以执行。

5)环境变量的相关路径

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

6)环境变量的组织方式

环境是一个字符指针数组,每个指针是指向一个以\0结尾的环境字符串,最后一个元素是NULL

7)获取环境变量的方法

a. 命令行第三个参数
#include<stdio.h>

int main(int argc,char *argv[ ],char *env[ ])
{
  int i=0;
  for(;env[i];++){
       printf("%s\n",env[i]);
       }
    return 0;
 }
b)通过第三方变量environ获取

environ指向环境变量表,没在任何头文件中,使用时,要用extern声明。

#include<stdio.h>

int main(int argc,char *argv[ ])
{
extern char **envision;
  int i=0;
  for(;environ[i];++){
       printf("%s\n",environ[i]);
       }
    return 0;
 }
c)通过getenv获取
#include<stdio.h>
#include<stdlib.h>


int main()
{
   printf("%s\n",getenv("PATH");
   return 0;
 }
getenv函数
头文件:#include<sdlib.h>
函数:char *getenv(const  char*name)
作用:用来获取name环境变量中的内容,name参数是环境变量的名称,如果该变量存在则返回指向该内容的指针,不存在则返回NULL。

putenv函数
头文件:#include<stdlib.h>
函数:int putenv(const char* string)
作用:用来改变环境变量的内容,如果环境变量存在,则变量内容会依照参数string改变,否则此参数内容成为新的环境变量
返回值:执行成功返回0,错误发生就返回-1
8)环境变量通常具有全局特性,可以被子进程集成下去。
#include<stdio.h>
#include<stdli.h>


int main()
{
   char *env=getenv("MYENY");
   if(env){
     printf("%s\n",env);
     }
     return 0;
 }

程序执行时,发现没有这个环境变量,但是执行命令export MYENV=“hello”,再次运行程序可以得到这个环境变量,说明环境变量可以被子进程继承export是把“变量”放到“环境”中,而环境变量是可以被子进程继承的。

2.进程地址空间

1)简单了解及图示

c语言时我们学习的空间分布图,用户使用的不是真正的物理内存,是虚拟的,不难理解,一个程序不可能使用完物理内存。
在这里插入图片描述

2)通过代码理解

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

输出结果为:

i am parent:[5884],0,0x80497d8
i am child:[5885],100,0x80497d8

我们发现父子进程的地址相同所以这个地址不是物理地址,在Linux下我们称为虚拟地址真正的物理地址由OS统一管理。用户一概看不到,OS必须负责将虚拟地址转换为物理地址。

3)同一个变量,地址相同,其实就是虚拟地址相同,内容不同就是被页表映射到不同的物理地址,如下图所示:

在这里插入图片描述
每一个进程都有一个PCB、虚拟地址空间、页表与维护映射关系。
当父进程创建一个子进程时,如果只读的化,父子进程的代码与数据是共享的,也就是说它们的虚拟地址空间与页表都是共享的,但是如果有一方试图修改数据,父子进程就以写时拷贝的方式数据各自私有一份,即虚拟地址空间与页表不同。

借助虚拟地址空间:可以实现资源独占,每个虚拟地址空间都是4G(32位),每个进程都可以认为它有4G的空间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值