进程地址空间与系统调用解析
1. 进程动态内存分配差异
在操作系统中,内核函数获取动态内存的方式较为直接,可调用多种函数,如__get_free_pages()或alloc_pages()从分区页框分配器获取页面,kmem_cache_alloc()或kmalloc()使用 slab 分配器处理专用或通用对象,vmalloc()或vmalloc_32()获取非连续内存区域。若请求能被满足,这些函数会返回页描述符地址或标识分配的动态内存区域起始位置的线性地址。
这种简单的分配方式可行有两个原因:
- 内核是操作系统中优先级最高的组件。若内核函数请求动态内存,必然有合理原因,无需延迟处理。
- 内核信任自身。所有内核函数被假定无错误,因此内核无需针对编程错误设置保护机制。
然而,为用户模式进程分配内存时,情况截然不同:
- 进程对动态内存的请求被视为非紧急的。例如,加载进程的可执行文件时,进程近期不太可能访问代码的所有页面。同样,进程调用malloc()获取额外动态内存,并不意味着会立即访问所获的所有额外内存。因此,通常内核会尝试延迟为用户模式进程分配动态内存。
- 由于不能信任用户程序,内核必须准备好捕获用户模式进程引发的所有寻址错误。
2. 进程地址空间
进程的地址空间由进程被允许使用的所有线性地址组成。每个进程看到的线性地址集合不同,一个进程使用的地址与另一个进