💬 欢迎讨论:如果你在学习过程中有任何问题或想法,欢迎在评论区留言,我们一起交流学习。你的支持是我继续创作的动力! 👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?别忘了点赞、收藏并分享给更多的小伙伴哦!你们的支持是我不断进步的动力! 🚀 分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对Linux OS感兴趣的朋友,让我们一起进步!
虚拟地址空间是指操作系统为每个进程提供的一个独立的内存空间,它与实际物理内存分离。每个进程都拥有自己的虚拟地址空间,操作系统通过内存管理单元(MMU)将虚拟地址映射到物理内存地址,实现了进程间内存的隔离和保护。虚拟地址空间使得每个进程似乎拥有从零开始的连续内存,避免了直接访问物理内存的复杂性,同时提供了更高的灵活性和安全性。
下面来段代码,来验证确实有虚拟地址的存在!
#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;
}
输出结果:
child[3046]: 100 : 0x80497e8 parent[3045]: 0 : 0x80497e8
通过现象可以看出,全局变量g_val在父子进程中值不相同,地址却相同。这里的地址就是虚拟地址,为什么值不一样,因为每个进程都会有独立的虚拟地址空间和一套页表(该页表作用:建立虚拟地址与物理地址的映射关系),OS会将虚拟地址转化为物理地址。
图来理解该过程更形象,如下图:
结论:上⾯的图就⾜矣说明问题,同⼀个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址!
OS将每个区域进行区域划分。用mm_struct结构体保存相关属性。 上述已经提到了每个进程都有地址空间,那么多的进程地址空间,OS需不需要管理呢???需要的,如何管理:先描述,再组织。
linux下进程的地址空间的所有的信息的结构体是 mm_struct (内存描述符)。每个进程只有⼀个mm_struct结构,在每个进程的task_struct结构中,有⼀个指向该进程的结构。
struct mm_struct { /…/ struct vm_area_struct mmap; / 指向虚拟区间(VMA)链表 / struct rb_root mm_rb; / red_black树 / unsigned long task_size; /具有该结构体的进程的虚拟地址空间的⼤⼩/ /…/ // 代码段、数据段、堆栈段、参数段及环境段的起始和结束地址。 unsigned long start_code, end_code, start_data, end_data; unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end; /…*/ }
mm_struct结构是对整个⽤⼾空间的描述。每⼀个进程都会有⾃⼰独⽴的mm_struct,这样每⼀个进程都会有⾃⼰独⽴的地址空间才能互不⼲扰。先来看看由task_struct到mm_struct,进程的地址空间的分布情况:
因为上述已经说过进程地址空间存在不同的区域,为了达到快速访问的目的,使用vm_area_struct来;连接各个虚拟内存区域(VMA)。
linux内核使⽤ vm_area_struct 结构来表⽰⼀个独⽴的虚拟内存区域(VMA),由于每个不同质的虚拟内存区域功能和内部机制都不同,因此⼀个进程使⽤多个vm_area_struct结构来分别表⽰不同类型的虚拟内存区域。上⾯提到的两种组织⽅式使⽤的就是vm_area_struct结构来连接各个VMA,⽅便进程快速访问。
struct vm_area_struct { unsigned long vm_start; //虚存区起始 unsigned long vm_end; //虚存区结束 struct vm_area_struct *vm_next, *vm_prev; //前后指针 struct rb_node vm_rb; //红⿊树中的位置 unsigned long rb_subtree_gap; struct mm_struct *vm_mm; //所属的 mm_struct pgprot_t vm_page_prot; unsigned long vm_flags; //标志位 struct { struct rb_node rb; unsigned long rb_subtree_last; } shared; struct list_head anon_vma_chain; struct anon_vma *anon_vma; const struct vm_operations_struct *vm_ops; //vma对应的实际操作 unsigned long vm_pgoff; //⽂件映射偏移量 struct file * vm_file; //映射的⽂件 void * vm_private_data; //私有数据 atomic_long_t swap_readahead_info; #ifndef CONFIG_MMU struct vm_region vm_region; / NOMMU mapping region */ #endif #ifdef CONFIG_NUMA struct mempolicy vm_policy; / NUMA policy for the VMA */ #endif struct vm_userfaultfd_ctx vm_userfaultfd_ctx; } __randomize_layout;
将上述结构进行量化,如图:
综上,虚拟地址空间不仅保障了内存的安全、管理简便,还提升了内存利用率和系统性能,是现代操作系统不可或缺的基础设施。
本文主要介绍了进程地址空间的基本概念及其管理方式。进程地址空间是操作系统为每个进程提供的独立内存区域,包括代码段、数据段、堆区和栈区等。通过虚拟内存管理,操作系统实现了进程间内存隔离和保护,确保了系统的安全性与稳定性。文章还阐述了虚拟地址空间的意义,包括内存隔离、简化内存管理、支持虚拟内存机制以及内存共享与优化等。通过这些机制,操作系统能够高效管理内存,提升系统性能和资源利用率,是现代操作系统不可或缺的基础。
路虽远,行则将至;事虽难,做则必成
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有