Linux进程地址空间详解

ram 的某些部分永久地分配给内核, 并用来存放内核代码以及静态内核数据结构. ram 的其余部分称为动态内存 (dynamic memory). 动态内存不仅是进程所需的宝贵资源, 也是内核本身所需的宝贵资源. 实际上,整个系统的性能取决于如何有效地管理动态内存. 因此, 现在所有多任务操作系统都在尽力优化对动态内存的使用, 也就是说, 尽可能做到当需要时分配, 不需要时释放.
当给内核分配动态内存时, 是相对容易的, 有如下两点原因:
内核是操作系统中优先级最高的成分. 如果某个内核函数请求动态内存, 那么, 必定有正当的理由发出这个请求, 因此, 没有道理试图推迟这个请求.
内核信任自己. 所有的内核函数都被假定是没有错误的, 因此内核函数不必针对程序错误施加任何保护措施.
而当给用户态进程分配内存时, 情况完全不同:
进程对动态内存的请求被认为是不紧急的. 例如, 当进程对应在磁盘上所存储的可执行文件被装入内存时, 进程并不一定会立即对所有的代码和数据进行访问. 类似地, 当进程调用 malloc() 以请求获得额外的动态内存时, 也并不意味着进程很快就会访问所获得的额外的动态内存. 因此, 一般来说, 内核总是尽量推迟给用户态进程分配动态内存.
由于用户进程是不可信任的, 因此, 内核必须能随时准备捕获用户态进程引起的所有寻址错误.
为了使得动态内存得到最大限度的使用, 内核使用一种新的资源成功实现了对进程动态内存的推迟分配. 当用户态进程请求动态内存时, 并没有获得请求的动态内存, 而仅仅得到了对一个新的线性地址区间的使用权, 这样的线性地址区间有很多, 由允许进程使用的全部线性地址区间所组成的集合就叫做进程地址空间.
与进程地址空间有关的全部信息都包含在一个叫做内存描述符的数据结构中 (实际上就是描述进程虚拟内存的数据结构), 这个结构的类型为 mm_struct, 进程描述符的 mm 字段就指向这个结构.
struct mm_struct *mm;如下为linux 2.6.11版的内核中mm_struct的实现.struct mm_struct { struct vm_area_struct * mmap; struct rb_root mm_rb; struct vm_area_struct * mmap_cache; unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); void (*unmap_area) (struct vm_area_struct *area); unsigned long mmap_base; unsigned long free_area_cache; pgd_t * pgd; atomic_t mm_users; atomic_t mm_count; int map_count; struct rw_semaphore mmap_sem; spinlock_t page_table_lock; struct list_head mmlist; * together off init_mm.mmlist, and are protected * by mmlist_lock */ 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; unsigned long rss, anon_rss, total_vm, locked_vm, shared_vm; unsigned long exec_vm, stack_vm, reserved_vm, def_flags, nr_ptes; unsigned long saved_auxv[42]; unsigned dumpable:1; cpumask_t cpu_vm_mask; mm_context_t context; unsigned long swap_token_time; char recent_pagein; int core_waiters; struct completion *core_startup_done, core_done; rwlock_t ioctx_list_lock; struct kioctx *ioctx_list; struct kioctx default_kioctx; unsigned long hiwater_rss; unsigned long hiwater_vm; };  
其中用来标识相应进程特定线性区的字段如下:
start_code, end_code
正文代码的起始地址和终止地址.
start_data, end_data
已初始化数据的起始地址和终止地址.
start brk, brk
堆的起始地址和当前终止地址.
start_stack
用户态堆栈的起始地址.
arg_start, arg_end
命令行参数的起始地址和终止地址.
env_start, env_end
环境变量的起始地址和终止地址.
如下为进程地址空间的布局, 由一个一个的线性地址区间组成, 线性地址 (linear address), 也称虚拟地址 (virtual address) 是一个 32 位无符号整数 (unsigned long), 可以用来表示数值高达 4gb 的地址, 也就是 4,294,967,296 个内存单元. 线性地址通常用十六进制数字表示, 值的范围从 0x00000000 到 0xffffffff.
0x00000000 ~ 0xbfffffff 这一线性地址区间被称为用户空间, 大小为 3gb; 而0xc0000000 ~ 0xffffffff 这一线性地址区间被称为内核空间, 大小为 1gb.
可以通过以下代码对进程地址空间的布局图进行验证.
#include #include int uninitialized_global_var;int initialized_global_var = 100;int main(int argc, char *argv[], char *envp[]){ printf(code address:%p, main); printf(initialized data address:%p, &initialized_global_var); printf(uninitialized data address:%p, &uninitialized_global_var); int *p = (int*)malloc(sizeof(int)); printf(heap address:%p, p); printf(stack address:%p, &p); for (int i = 0; i lru_lock ! */ * on machines where all ram is mapped into kernel address space, * we can simply calculate the virtual address. on machines with * highmem some memory is mapped into kernel virtual memory * dynamically, so we need a place to store that address. * note that this field could be 16 bits on x86 ... ;) * * architectures with slow multiplication can define * want_page_virtual in asm/page.h */#if defined(want_page_virtual) void *virtual; not kmapped, ie. highmem) */#endif };  
cpu 管理物理地址, 因而虚拟地址需要转化为物理地址才能给 cpu 使用. 用于将进程(虚拟)地址空间映射成物理地址空间的数据结构称为页表.
进程地址空间, 页表的存在有什么意义?
让所有进程以统一的视角看待内存, 进程地址空间的存在让我们在编写程序的时候只需关注虚拟地址, 而无需关注数据在物理内存当中实际的存储位置.
页表的存在让进程在间接访问内存的时候, 增加一个转换的过程, 在这个转换的过程中, 内核对进程的寻址请求进行检查, 如果该进程的寻址请求异常, 则该请求被操作系统拦截, 从而实现对物理内存的保护.
进程地址空间与页表的存在, 让内核对于进程管理模块与内存管理模块进行了解耦.


全面解析温室大棚地源热泵工作原理及优缺点
目前中国平板电脑市场的缺货状态至少会持续到 2020 年底?
NB-IoT\eMTC\LoRa对于物联网发展的作用
HIL仿真技术监测和诊断发动机燃烧性能
丰田携手腾讯改进网联汽车安全功能
Linux进程地址空间详解
为什么说激光SLAM是机器人自主行走不可绕过的核心?
语音识别芯片哪个最好 语音识别技术哪家强
石墨电极是什么东西
如何在工程应用中合理采用并行编程技术
奇怪的基于BC547-NPN震荡演示电路
超级电容器在混合动力汽车和能量收集中的应用
当学生用喵喵机整理错题,智能化带来哪些效率升级?
米8新品发布会:小米会发布MIUI10、小米8、小米手环3等新品
一份达标的多功能电力仪表说明书包括什么內容
高端进口品牌 十大净水品牌凯菲勒2020扬帆起航!
苹果宣布推出自助维修计划 明年美国率先启动
南德意志为光纤通信系统安全提供全方位的测试服务
高集成和无感FOC发展趋势下的BLDC专用驱控芯片
基于RoboMasterC板的RT-Thread使用分享—PWM使用