Process address space/进程地址空间
简介
在这片文章中,我介绍了关于进程的地址空间的相关内容,首先介绍了进程地址空间的定义,和它的大小,然后介绍了在内核源码中实现的方式mm_struct,之后介绍了其中进程能够访问的部分VMA,以及VMA在内核源码中实现的结构
参考
Linux内核设计与实现 第15章节
https://zhuanlan.zhihu.com/p/66794639
感谢
Photo by Tanguy Sauvin: https://www.pexels.com/photo/turtle-swimming-underwater-10467/
什么是process address space/进程地址空间
所谓进程地址空间(process address space),就是从进程的视角看到的地址空间,是进程运行时所用到的虚拟地址的集合。
进程地址空间是虚拟地址
进程地址空间是程序运行的时候用到的虚拟地址
process address space的大小和分布
进程地址空间有多大呢?在32位有4gb大小,而64位则会上tb的级别,当然,这些都是虚拟出来的!
https://zhuanlan.zhihu.com/p/66794639
内核和用户空间的区别
用户进程和内核进程的进程地址空间会有区别吗?
什么是flat address space/平坦地址空间
?
什么是memory areas/内存区域
能够被进程访问到的地址空间才是memory areas
进程地址空间对应的内核结构
mm_struct结构描述了一个进程的进程地址空间的全部信息,定义在mm_types.h中
https://elixir.bootlin.com/linux/v5.15.82/source/include/linux/mm_types.h#L402
mm_struct中的重要组成部分
mmap和mm_rb
分别用链表和红黑树记录了该地址空间的全部内存区域
mmlist
操作系统中全部的mm_struct组成的链表
各种特殊区域的地址
1 | unsigned long start_code,end_code,start_data,end_data; |
代码段code,数据段data,堆brk的首尾地址
栈stack的开始地址
命令行参数的首尾地址
环境变量的首尾地址
计数
有两个变量记录了正在使用该内存区域的计数
mm_users是正在使用该区域的线程数
mm_count是待定
mm_users/mm_conut
1 | https://www.quora.com/Linux-Kernel-Why-are-we-using-two-variables-mm_users-and-mm_count-in-mm_struct |
进程地址空间可访问的部分-VMA
什么是VMA
进程地址空间有多大呢?在32位有4gb大小,而64位则会上tb的级别,当然,这些都是虚拟出来的!
而这么大的区域,其实能够被使用的部分才是真正有意义的,毕竟,看的到不一定能摸得到,笑
进程地址空间是一个进程看到的最大的空间,而一个进程能够访问的部分,才是最有价值的,叫做 memory areas/内存区域 ,在内核中使用vm_area_struct描述
memory areas/内存区域,在linux中也叫做 virtual memory areas,虚拟内存区域/VMA,这些名词都是同一个意思
最常被使用的叫法是VMA
定义
The kernel uses virtual memory areas to keep track of the process’s memory mappings; for example, a process has one VMA for its code, one VMA for each type of data, one VMA for each dist7inct memory mapping (if any), and so on. VMAs are processor-independent structures, with permissions and access control flags. Each VMA has a start address, a length, and their sizes are always a multiple of the page size (PAGE_SIZE). A VMA consists of a number of pages, each of which has an entry in the page table.**–by Linux Device Drivers Development
常见的VMA
一般来讲,一个进程都会有以下的vma
text section | 代码段 | 可执行文件代码的内存映射 |
---|---|---|
data section | 数据段 | 可执行文件的已初始化全局变量的内存映射 |
bss段 | 可执行文件的未初始化全局变量的内存映射 | |
进程地址空间的所属情况
每一个进程都会有它自己的进程地址空间,一个进程的所有的线程共享一个进程地址空间。在linux中,线程就是一种共享进程地址空间的进程,都是使用task_struct描述的,而没有单独的结构