一.环境变量的概念:

环境变量就是系统 / Shell 提前给程序准备好的「全局备用参数」,所有程序都能直接拿来用,不用自己重新配置。下面是一个例子:

main函数的参数:

  • argc:参数个数(argument count)
  • argv:参数字符串数组(argument vector)

main 参数怎么实现选项(原理)

  1. 你在终端输入:./a.out -l -o test.txt
  2. 系统把整行拆成字符串数组,放进 argv
  3. 程序里循环遍历 argv
  4. 判断字符串是不是 -l-o
  5. 匹配到就执行对应功能

1.我们运行程序就必须先找到该程序,bash帮你找到程序,通过PATH(环境变量)来找

我们在运行code可执行文件时,需要./code,但是将路径改到PATH里面就可以直接code就可以执行程序了

2.系统中存在环境变量(PATH),来帮助系统找到目标二进制文件,环境变量的作用是在系统中搜索指令的默认搜索路径

环境变量的构成

名称=内容

查看所有环境变量env

env//查看所有环境变量

查看一个环境变量的内容:echo $PATH

PATH环境变量:

你在命令行输入命令时,系统会自动去 PATH 里的所有目录找这个程序,找到就运行,找不到就报错。可以对PATH进行更改

1.$ PATH=一个你自己的路径.会将原来的路径覆盖,我们就不能使用ls等系统命令了,重启就可以恢复.

2.$ PATH=$PATH:一个你自己的路径,会在原来的路径基础上加一个你自己添加的路径,重启会进行恢复.

export PATH=$PATH:你的自定义路径
 

环境变量是从系统中的相关配置文件中来的

认识更多环境变量

环境变量HOME当前用户的家目录,就是它的简写,系统和程序都靠它定位用户个人文件夹。

环境变量 SHELL 保存的是:当前用默认使用的 Shell 程序的完整路径

环境变量USER,USER 保存当前登录的用户名

环境变量HISTSIZE,HISTSIZE 是控制 Bash 内存中命令历史记录数量的环境变量,bash只会保存最新的1000条指令

环境变量HOSTNAME,HOSTNAME表示当主机的主机名

环境变量OLDPWD,自动记录你上一次待过的文件夹路径,cd- 就可以直接到上一路径

环境变量是一些参数bash去找到并且去使用它,就等于用户去使用它,bash里面包括环境变量表和命令参数表

获得环境变量的方法

可以自己导入环境变量

exprot "环境变量名"

同样的也可以取消环境变量

unset "环境变量名"

方式一:

在代码中也可以获取环境变量main函数还有一个参数是char *env[],对指针数组进行遍历就可以拿到所有的环境变量.

#include <stdio.h>

int main(int argc, char *argv[], char *env[])
{
    for(int i=0; env[i]; i++)
    {
        printf("env[%d] -> %s\n", i, env[i]);
    }
    return 0;
}

环境变量可以被子进程继承,所有的子进程都可以拿到,所以环境变量通常有全局特性.为什么环境变量需要被子进程继承?

方式二:

使用getenv()库函数获取环境变量,这可以找到具体的环境变量.

#include <stdio.h>
#include <stdlib.h>

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

方式三:

environ = 系统全局的环境变量表指针,它就是一个全局变量,任何地方都能用,直接指向当前进程所有的环境变量

二.程序地址空间:

进程地址空间(虚拟地址空间):

程序空间地址不是内存地址或者物理内存,是虚拟地址.C/C++指针用到的地址,全部都是虚拟地址.

子进程拷贝父进程的虚拟地址,发生了浅拷贝(指针拷贝),所以代码共享,数据共享,但是进程具有独立性,所以在子进程修改的时候操作系统会重新开空间再进行修改,我们叫做写时拷贝.只读不改变变量,只要有一方改变

  • 给修改的进程单独分配一块新物理内存
  • 把原来数据复制过去
  • 自己改自己的,互相彻底隔离

虚拟地址与进程地址空间

1.每个进程都以为自己独占了整块完整内存,这一块 “假装独有的内存布局”,就像老板画大饼,给你都以为是独占的资源,就是虚拟地址空  间,虚拟地址空间就是那个"饼".

CPU、程序代码里用的所有地址,全是虚拟地址,不是真实物理内存地址。

我们不仅需要管理进程,我们还需要区管理那些"饼",免得老板的"饼"发错了,同样的我们要管理就要先描述,再组织.画一个"饼"就定义一个节点,就变成对数据结构的管理.这个数据结构叫做mm_struct

  2.区域划分:

起始地址、结束地址记录下来.中间的所有地址都可以用

3.调整区域

对虚拟地址的       起始地址,结束地址进行加减就改变了. 

为什么需要虚拟地址空间和页表:

页表里面有每个虚拟页 → 物理页框的映射关系,还有保护位(里面是读写执行权限)

1.将地址从无序变有序  

就像你的压岁钱给你妈妈,妈妈说一要买什么再给你但是,真要的时候是不太可能成功的,所以妈妈起到了保护作用.

2.地址转化的过程中,也可以对你的地址和操作进行合法性的判定,进而保护物理内存

a.野指针

b.在字符常量区写入,程序会崩溃,,在页表查询的时候,权限被拦截了.

3.让进程和内存管理,进行一定程度的解耦合

缺页中断:

进程运行时,CPU 要访问某个虚拟页面,但这个页面不在物理内存里,只在外存(磁盘)上,此时 CPU 触发缺页中断,由操作系统介入处理,把页面从磁盘调入内存.

进程具有独立:

1.内核数据结构独立

2.加载进入内存内容的代码和数据的独立

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐