进程(二)----环境变量、虚拟地址访问物理空间、内存管理方式

进程优先级:一个进程对与CPU资源获取的优先权

为什么要有优先级?(让操作系统运行的更加良好)
交互式进程:直接与用户进行交互的进程,(要求最好能够更加有限的被CPU处理)。
批处理进程:在后台默默做循环工作的进程。
环境变量:配置系统运行环境参数的变量。
环境变量优点使系统运行环境配置更加简单灵活,可以通过设置环境变量给一个进程传递参数信息。(不用再去修改配置文件,重新加载配置文件,而是直接设置直接生效)

环境变量的操作

查看环境变量:env/set(查看所有变量,包含环境变量)/echo直接打印某一环境变量
设置环境变量:export
删除环境变量:unset
环境变量是具有继承性的:子进程也拥有父进程的环境变量
典型:PATH- - - - -系统命令程序的默认搜索路径

代码中环境变量的操作

  • main函数的第三个参数 int main(int argc,char *argv[ ],char *env[ ])…env保存环境变量
  • 通过一个全局变量eexern char **environ;…environ保存环境变量
  • char *getenv(const char *name);…通过环境变量名称获取一个指定环境变量的数据

变量的声明:就是告诉编译器,有这个变量的存在(但是这个变量不一定是我们自己定义的,这个声明使用的变量通常是一个本文件之外的全局变量 a.c / b.c)
变量的定义:告诉编译器这个变量是什么样子的
exetrn char **enciron;在本文件中声明有这个变量/然而这个变量的具体内容实际上是外部的,是标准库中存的。

程序地址空间

地址:对内存单元的编号
程序时不占用内存的,运行起来的程序被加载到内存,才会占有内存。

  • 进程地址空间- - - -一个全局变量,在子进程中修改后,打印100,但父进程中依然打印1, 数据不同,表示肯定没有使用同一块内存空间(一块内存空间不可能存储两个数据),父子进程打印的数据不同但是地址却是相同的- - - - - 矛盾
  • 实际上进程中访问的地址都是虚拟地址,而我们所说的程序地址空间实际上是一个进程的虚拟地址空间;
    虚拟一个地址空间:其实就是一个结构体 mm_struct;- - - - - 是一个对内存空间的描述- - - - -通过这个描述向进程虚拟出一个完整的、连续的内存空间;为了能够直接访问物理内存
    size :示内存大小
    code_start/code_end:描述代码段的起始与结束,通过这两个信息就可以描述一块空间。

进程直接访问物理内存:

  • 1、进程中的代码使用都是连续的地址,若直接使用连续的物理内存会造成内存的浪费;
  • 2、直接访问物理内存会因为缺乏内存访问控制导致进程的不安全。
    在这里插入图片描述

如何通过虚拟地址访问物理内存?

  • 操作系统为进程创建mm_struct虚拟地址空间的同时,也创建了一个页表用于映射虚拟地址与物理地址的关系;
  • 进程使用虚拟地址空间,通过页表映射物理内存,可以实现进程中数据在物理内存上的离散式存储,通过这种方式提高内存的利用率;
  • 在页表中可以直接针对某个地址设置,这个地址的访问权限(这个地址是只读的),通过这种方式实现内存访问控制

为什么要使用虚拟地址空间?

  • 这些虚拟地址最终通过页表映射到物理内存上实现数据离散式存储(提高内存访问率);
  • 在页表中实现内存的访问控制。

写时拷贝技术:两个一开始指向同一块空间,等待发生改变的时候,再给子进程重新开辟空间,目的就是提高子进程创建效率。

操作系统通过虚拟地址空间,给每一个进程都虚拟的描述了一个完整的、独立的地址空间,虚拟地址空间可以让进程依然使用连续的虚拟地址,通过页表映射之后,实现数据在物理内存上的离散式存储,提高内存利用率。
每个进程都有一个虚拟地址空间,有一个页表,并且通过页表可以实现内存访问控制,进一步提高进程的独立性。

页表的主要功能:映射虚拟地址与物理地址的关系/提供内存访问控制。
页表如何实现通过虚拟地址访问物理地址?- - - - - MMU

内存管理方式

分页式内存管理(提高内存利用率)

将物理内存进行分块管理,通过页表映射实现数据在物理内存上的离散式存储。
分页式内存管理的虚拟地址组成:页号 + 页内偏移
页号:页表中页表项的编号
业内偏移:具体一个变量首地址相当于内存起始位置的偏移量

物理地址 = 物理内存块 * 物理内存块大小 + 虚拟地址中的页内偏移
在这里插入图片描述

分段式内存管理(内存管理更加方便)

内存组成:段号 + 段内偏移
在这里插入图片描述

段页式内存管理(集合了分页式和分段式的优点)

每个分段都有一个页表,通过地址中的段号,找到段表项,通过段表项中段内页表起始位置找到自己的页表,通过地址中的段内页号,在这个页表中找到页表项,通过页表项中的物理块号 + 页内偏移得到最终的物理地址
地址组成:段号 + 段内页号 + 页内偏移 + 段表 + 段内页表 (在每一个分段内,又采用分页式管理)

编译器在编译
编译器在编译程序的时候就会为每一个指令以及数进行地址的分配(一个程序使用哪些地址,在编译链接完成后就已经定下了),如果直接使用物理内存,哪个程序现在用了哪些地址,否则有可能造成冲突,都可以随意使用连续地址信息,在加载到内存中农运行时计算一个总体偏移量。
在这里插入图片描述
直接访问物理内存会存在一个问题:一个指针随意赋值是一件可怕的事情,进程之间可以随意通过地址访问其他进程的空间以及数据,缺乏内存访问控制

缺页中断

磁盘可以分为:交换分区 和 文件系统分区。
交换分区:作为交换内存使用。

当内存不够的时候,这时候由于内存中并不是所有是数据都是活跃数据,操作系统会根据一定的算法,将某块内存中数据保存到磁盘的交换分区中,腾出这块内存加载新数据,但是每个进程的页表中记录了每一个虚拟地址对应的物理地址,如果这个虚拟页面的物理内存中的数据被交换出去了,保存到交换分区,则将这个页表项设置为缺页中断。等待下次这个进程要访问这个被交换出去的数据的时候(这个数据当前没在内存中,而是保存在交换分区中),触发缺页中断,重新从交换分区将数据交换回来。

LRU:一种内存置换算法- - - - -最久未使用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章