目录
虚拟地址
初识
由代码看现象:
最后发现g_val变化了而父进程还是100子进程为300了,是因为父子进程具有独立性,不要把独立性理解为不相往来。而我们有知道进程=内核数据结构(task_struct)+代码和数据,那么就知道每个进程拥有独立自己的task_struct和代码数据,代码是只读的因为共享代码。
而我们发现子与父的g_val的地址空间一样但是为什么数据却不同?首先我们知道的是&g_val一定不是物理地址,如果是物理地址的话怎么可能访问一个是100一个是300。那它是虚拟地址
基本理解

如果一个全局变量,父子进程对它不写,那么默认他是被父子进程共享的因为代码共享,打印出的值和地址也是一样的,父子进程都指向同一个物理地址也是同一个虚拟地址。
可不可以把数据在创建子进程的时候,全部给子进程拷贝一样?不能。主要原因为父进程有很多数据,子进程不会修改甚至很少修改那么会浪费空间,那么对于不会修改的就共享们对于修改的就写时拷贝即按需申请
同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了 不同的物理地址!
我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理
OS必须负责将虚拟地址转化成物理地址 。
细节理解
如何理解地址空间
什么是划分区域?
区域划分可以理解为桌子划分区域(三八线)在区域内属于谁,另一个人不越界。
地址空间的理解:
可以理解为os给每个进程画大饼--地址空间(形容虚拟的),就是告诉进程你有这么大的空间。
为什么要有地址空间?
如果没有虚拟空间那么可执行程序运行后代码和数据在内存中,那么进程的pcb就要直接到内存中找对应的代码和数据,只不过进程得记录内存中的位置。如果有多个程序的话,那么就要求每个进程都要记录对应的位置,那么对于进程来说负担比较大(因为代码和数据可能不在一起,在内存中不同区域)。
有地址空间的话,进程pcb就指向地址空间,再通过页表找到相应的物理空间。
在实际的物理内存中,代码区,数据区,堆区,栈区,共享区,命令行参数区和环境变量可能时乱序排的。但是有了页表和地址空间后,进程一一对应地址空间的各个区(是有序的,从低地址到高地址),再通过页表查询。
PCB 通常包括以下信息:
进程状态:进程的当前状态,如运行、就绪、阻塞等。
程序计数器:记录进程下一条要执行的指令的地址。
寄存器内容:保存进程在切换时的寄存器状态。
内存管理信息:包括基址寄存器、界限寄存器(在一些系统中)、页表或段表的指针等。
文件描述符:进程打开的文件和资源的描述符。
调度信息:优先级、调度队列中的位置等。
进程标识符:进程ID等标识信息。
程序的代码和初始化数据确实会存在于物理内存中,但它们是通过虚拟地址空间映射到物理内存的。虚拟地址空间中的这些数据会通过操作系统的内存管理单元(MMU)映射到物理内存中。当程序运行时,内存管理单元(MMU)将虚拟地址转换为物理地址,确保程序可以访问它需要的数据和指令。这种映射机制使得程序在运行时可以透明地使用虚拟地址来访问数据,而操作系统则管理实际的物理内存分配。
操作系统利用 PCB 中的内存管理信息(如页表或段表)来实现虚拟地址到物理地址的转换,从而确保进程能够正确访问其代码和数据。
操作系统通过 PCB 中记录的虚拟地址范围来管理进程的内存。在具体操作过程中,操作系统并不直接查找数据,PCB 中的虚拟地址范围主要用于内存管理和地址转换的参考,操作系统通过页表和 MMU 等机制来实际管理和访问内存中的数据。
内存管理和地址映射
代码区和数据区的定位
内存管理单元(MMU):在现代操作系统中,内存管理单元负责将进程的虚拟地址映射到物理内存地址。PCB 中的内存管理信息(如页表或段表)帮助操作系统实现这一映射。虚拟内存:进程使用的内存地址是虚拟地址,而实际的物理内存地址由操作系统和硬件共同管理。PCB 中记录的虚拟地址空间的起始地址和大小帮助操作系统确定代码区和数据区的具体位置。
内存分配和访问
程序加载:当程序被加载到内存时,操作系统会将其代码和数据分配到虚拟内存中的适当位置。这些地址范围会被记录在 PCB 中的内存管理信息里。地址转换:在运行时,操作系统使用 PCB 中的内存管理信息(例如,页表或段表)将进程的虚拟地址转换为物理地址。这样,CPU 就可以访问实际的物理内存区域。
访问控制:代码区通常是只读的,以保护程序代码不被修改。数据区、堆区和栈区的访问权限则可能根据需求有所不同。PCB 中的内存管理信息帮助操作系统实施这些访问控制策略。
那么页表和地址空间存在的意义:
1.就是将无序变有序,让进程以统一的视角看待物理内存以及自己运行的各个区域。
2.进程管理模块和内存管理模块进行解耦
也就是说进程申请空间只需在地址空间申请就可以,地址空间再在页表的左侧写东西右侧可先不填,当需要的时候再用再映射(内存使用率非常高),防止申请了又不用(或者没用完)可能会占用空间导致其他进程内有足够的空间访问。3.拦截非法请求
新增一个途径,作为中间层拦截非法访问。其实就是物理内存进行保护,防止越界访问修改。页表还可以用于内存保护,确保进程不能访问不属于它的内存区域。
如何进一步理解页表和写时拷贝:

如何理解虚拟地址?
在最开始的时候,地址空间和页表的数据从哪里来的?都是从可执行程序里读来的
程序里面本身就有地址,只不过这个地址是虚拟地址(逻辑地址)