进程如何管理和分配虚拟地址空间的?
分治思想
内核通过mm_struct来描述一个进程的虚拟地址空间,按照不同的属性和功能对虚拟内存进行划分,划分为一个个VMA
- 代码段.text
- 数据段.data
- bss
- lib库的代码段
- lib库的数据段
- lib库的bss
- 任何内存映射文件(有名mmap建立)
- 任何共享内存段(匿名mmap建立)
- 进程栈stack
- 进程堆heap
在linux系统上通过cat /proc/pid/maps
命令查看虚拟内存结构:
每一列的含义分别为
实际的结构:
mm_struct
398 struct mm_struct {
399 struct vm_area_struct * mmap; /* list of VMAs */ //虚拟地址空间结构体,双向链表包含红黑树节点访问到不能访问的区域。
400 struct rb_root mm_rb; //红黑树的根节点
401 struct vm_area_struct * mmap_cache; /* last find_vma result */ //mmap的高速缓冲器,指的是mmap最后指向的一个虚拟地址区间
402 #ifdef CONFIG_MMU
403 unsigned long (*get_unmapped_area) (struct file *filp,
404 unsigned long addr, unsigned long len,
405 unsigned long pgoff, unsigned long flags);
406 void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
407 #endif
408 unsigned long mmap_base; /* base of mmap area */ //mmap区域的基地址
409 unsigned long mmap_legacy_base; /* base of mmap area in bottom-up allocations */ //自底向上的配置
410 unsigned long task_size; /* size of task vm space */ //进程的虚拟地址空间大小
411 unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ //缓冲器的最大的大小
412 unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ //不受约束的空间大小
413 unsigned long highest_vm_end; /* highest vma end address */ //虚拟地址空间最大结尾地址
414 pgd_t * pgd; //页表的全局目录
415 atomic_t mm_users; /* How many users with user space? */ //有多少用户
416 atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */ //有多少用户引用mm_struct
417 atomic_long_t nr_ptes; /* Page table pages */ //页表
418 int map_count; /* number of VMAs */ //虚拟地址空间的个数
419
420 spinlock_t page_table_lock; /* Protects page tables and some counters */ //保护页表和用户
421 struct rw_semaphore mmap_sem; //读写信号
422
423 struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung
424 * together off init_mm.mmlist, and are protected
425 * by mmlist_lock
426 */
427
428
429 unsigned long hiwater_rss; /* High-watermark of RSS usage */ //标志
430 unsigned long hiwater_vm; /* High-water virtual memory usage */
431
432 unsigned long total_vm; /* Total pages mapped */
433 unsigned long locked_vm; /* Pages that have PG_mlocked set */
434 unsigned long pinned_vm; /* Refcount permanently increased */
435 unsigned long shared_vm; /* Shared pages (files) */
436 unsigned long exec_vm; /* VM_EXEC & ~VM_WRITE */
437 unsigned long stack_vm; /* VM_GROWSUP/DOWN */
438 unsigned long def_flags;
439 unsigned long start_code, end_code, start_data, end_data; //开始代码段,结束代码。开始数据,结束数据
440 unsigned long start_brk, brk, start_stack; //堆的开始和结束。
441 unsigned long arg_start, arg_end, env_start, env_end; //参数的起始和结束,环境变量的起始和终点
442
443 unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
...
};
vma
281 struct vm_area_struct {
282 /* The first cache line has the info for VMA tree walking. */ //第一个高速缓存行包含VMA树便利的信息
283
284 unsigned long vm_start; /* Our start address within vm_mm. */ //虚拟地址空间vm_mm起始地址
285 unsigned long vm_end; /* The first byte after our end address
286 within vm_mm. */ //在vm_mm中结束地址的第一个字节
287
288 /* linked list of VM areas per task, sorted by address */
289 struct vm_area_struct *vm_next, *vm_prev; //双向链表连接以便于遍历
290
E>291 struct rb_node vm_rb; //红黑树节点
292
293 /*
294 * Largest free memory gap in bytes to the left of this VMA. //VMA左边最大的可用内存缺口
295 * Either between this VMA and vma->vm_prev, or between one of the
296 * VMAs below us in the VMA rbtree and its ->vm_prev. This helps //要么在当前的VMA和vma的前一个,要么是在VMA红黑树和它的前 一个中的VMAs之间
297 * get_unmapped_area find a free area of the right size. //这样有助于get_unmapped_area找到合适的空闲区域
298 */
299 unsigned long rb_subtree_gap; //红黑树子树的缺口
300
301 /* Second cache line starts here. */
302
302
303 struct mm_struct *vm_mm; /* The address space we belong to. */ //进程拥有的地址空间
E>304 pgprot_t vm_page_prot; /* Access permissions of this VMA. */ //此VMA访问权限
305 unsigned long vm_flags; /* Flags, see mm.h. */ //标志
306
307 /*
308 * For areas with an address space and backing store,
309 * linkage into the address_space->i_mmap interval tree, or
310 * linkage of vma in the address_space->i_mmap_nonlinear list. //作为地址空间和后备存储区域,链接到间隔树或者链接到非线性链 表里的vma
311 */
312 union {
313 struct {
314 struct rb_node rb;
315 unsigned long rb_subtree_last;
316 } linear; //线性
317 struct list_head nonlinear; //链表非线性
318 } shared;
319
320 /*
321 * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
322 * list, after a COW of one of the file pages. A MAP_SHARED vma
323 * can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
324 * or brk vma (with NULL file) can only be in an anon_vma list. //MAP_SHARED只能 在i_mmap树。匿名的对象,栈或者堆只能存在链表 里
325 */
326 struct list_head anon_vma_chain; /* Serialized by mmap_sem &
327 * page_table_lock */
328 struct anon_vma *anon_vma; /* Serialized by page_table_lock */
329
330 /* Function pointers to deal with this struct. */
331 const struct vm_operations_struct *vm_ops; //虚拟内存
332
333 /* Information about our backing store: */
334 unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
335 units, *not* PAGE_CACHE_SIZE */
336 struct file * vm_file; /* File we map to (can be NULL). */ //指向的文件
337 void * vm_private_data; /* was vm_pte (shared mem) */
...
};
进程与线程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人