一篇读懂Linux内核-内核地址空间分布和进程地址空间( 四 )


一篇读懂Linux内核-内核地址空间分布和进程地址空间

文章插图
 
如果系统调用do_mmap的参数中有无效参数,那么它返回一个负值;否则,它会在虚拟内存中分配一个合适的新内存区域,如果有可能的话,将新区域和临近区域进行合并,否则内核从vm_area_cach
ep长字节缓存中分配一个vm_area_struct结构体,并且使用vma_link()函数将新分配的内存区域添加到地址空间的内存区域链表和红黑树中,随后还要更新内存描述符中的total_vm域,然后才返回新分配的地址区间的初始地址 。在用户空间,我们可以通过mmap()系统调用获取内核函数do_mmap()的功能,这个在unix环境高级编程中讲的很详细,我就不好意思继续说了 。我们继续往下走 。
我们说既然有了创建,当然要有删除了,是不?do_mummp()函数就是干这事的 。它从特定的进程地址空间中删除指定地址空间,该函数定义在文件linux/mm.h中,如下:
int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
第一个参数指定要删除区域所在的地址空间,删除从地址start开始,长度为len字节的地址空间,如果成功,返回0,否则返回负的错误码 。与之相对应的用户空间系统调用是munmap 。
下面开始最后一点内容:页表
我们知道应用程序操作的对象是映射到物理内存之上的虚拟内存,但是处理器直接操作的确实物理内存 。所以当应用程序访问一个虚拟地址时,首先必须将虚拟地址转化为物理地址,然后处理器才能解析地址访问请求 。这个转换工作需要通过查询页面才能完成,概括地讲,地址转换需要将虚拟地址分段,使每段虚地址都作为一个索引指向页表,而页表项则指向下一级别的页表或者指向最终的物理页面 。linux中使用三级页表完成地址转换 。多数体系结构中,搜索页表的工作由硬件完成,下表描述了虚拟地址通过页表找到物理地址的过程:
一篇读懂Linux内核-内核地址空间分布和进程地址空间

文章插图
 
在上面这个图中,顶级页表是页全局目录(PGD),二级页表是中间页目录(PMD).最后一级是页表(PTE),该页表结构指向物理页 。上图中的页表对应的结构体定义在文件asm/page.h中 。为了加快查找速度,在linux中实现了快表(TLB),其本质是一个缓冲器,作为一个将虚拟地址映射到物理地址的硬件缓存,当请求访问一个虚拟地址时,处理器将首先检查TLB中是否缓存了该虚拟地址到物理地址的映射,如果找到了,物理地址就立刻返回,否则,就需要再通过页表搜索需要的物理地址 。




推荐阅读