Linux内核设计与实现 十五、进程地址空间

进程地址空间
 内核除了管理本身的内存外,还必须管理用户空间中进程的内存。我们称这个内存为进程地址空间,也就是系统中每个用户空间进程所看到的内存。

虚拟内存技术

 Linux采用虚拟内存技术,系统中所有进程之间以虚拟方式共享内存。对一个进程而言,它好像可以访问整个系统的所有物理内存。
 即使单独一个进程,它拥有的地址空间也可以远远大于系统物理内存。

15.1 地址空间

进程地址空间
 进程地址空间由进程可寻址的虚拟内存组成,内核允许进程使用这种虚拟内存中的地址。每个进程都有一个32位或64位平坦地址空间。平坦是指地址空间范围是一个独立的连续区间。

内存地址
 内存地址是一个给定的值,要在地址空间范围之内,尽管一个进程可以寻址4GB的虚拟内存(32位),但并不代表它有权访问所有的虚拟地址。可被访问的合法地址空间称为内存区域。
权限
 进程之内访问有效内存区域内的内存地址,每个内存区域具有相关权限如可读、可写、可执行属性。如果一个进程访问了不在有效范围中的内存区域,或以不正确的方式访问了有效地址,那么内核就会终止该进程,并返回“段错误”信息。

内核内存对象
●代码段:可执行文件代码的内存映射
●数据段:可执行文件的已初始化全局变量的内存映射
●未初始化全局变量
●进程用户空间栈:与进程内核栈不同
●共享库的代码段、数据段和bss也会被载入进程的地址空间
●任何内存映射文件
●任何共享内存段
●任何匿名的内存映射,比如由malloc()分配的内存
在这里插入图片描述

15.2 内存描述符

mm_struct

 内核使用内存描述符结构体表示进程的地址空间,该结构包含了和进程地址空间有关的全部信息。进程描述符task_struct中的mm域指向该结构

其余见书和CSAPP第九章

分配内存描述符

父子进程
 如果父进程希望和子进程共享地址空间,可以在调用clone()时,设置CLONE_VM标志。这样的进程称为线程。
线程对于内核来说仅仅是一个共享特定资源的进程而已。

撤销内存描述符

 进程退出时,内核会调用exit_mm()函数,该函数执行撤销工作

mm_struct与内核线程

 内核线程没有进程地址空间,也没有相关的内存描述符,所以内核线程对于的进程描述符中mm域为空。内核线程没有用户上下文。

 内核线程被调度时,内核发现mm域为NULL,就会保留前一个进程的内存描述符。所以在需要时,内核线程可以使用前一个进程的页表。因为内核线程不放我用户空间的内存,所以它们仅仅使用地址空间中和内核内存有关的信息。

15.3 虚拟内存描述符

 虚拟内存区域由vm_area_struct结构体描述。

功能

 描述了指定地址空间内连续区间上的一个独立内存范围。内核将每个内存区域作为一个单独的内存对象管理。每一个VMA就可以代表不同类型的内存区域(比如内存映射文件或者进程用户空间栈)。

结构体

在这里插入图片描述

关系

●task_struct 进程描述符,里面保存了许多关于进程控制的信息。
●mm_struct 内存描述符,包含了和进程地址空间有关的全部信息
●vm_area_struct 虚拟内存描述符,描述了指定地址空间内连续区间上的一个独立内存范围
在这里插入图片描述

VMA标志

概念
 是一种位标志,包含在vm_flags域内,标志了内存区域所包含的页面的行为和信息,和物理页的访问权限不同,VMA标志反映了内核处理页面所需要遵守的行为准则,而不是硬件要求

操作
 vm_ops域指向与指定内存区域相关的操作函数表

内存区域的树型结构和内存区域的链表结构

内核为了内存区域上各种不同操作都能获得高性能,同时使用了两种数据结构。
●mmap:
 链表连接所有的内存区域对象。每一个vm_area_struct结构体通过自身的vm_next域被连入链表,所有的区域按地址增长的方向排序。mmap执行链表第一个内存区域。

 适用于遍历全部节点时。

●mm_rb:
 红黑树连接所有的内存区域对象。mm_rb域指向红黑树的根节点,地址空间每一个vm_area_struct结构体指针指向空。

 适用于查找定位特定内存区域时。

实际使用的内存区域

 如果一片内存范围是共享的或不可写的,内核只需要在内存中为文件保留一份映射,如C库在物理内存仅需占用1212KB空间,而不需要为每个使用C库的进程在内存中都保存一个1212KB的空间。利用共享不可写内存的方法节约了大量的内存空间。

15.4 操作内存区域

 内核时常需要在某个内存区域上执行一些操作,比如某个指定地址是否包含在某个内存区域中。这类操作非常频繁

find_vma
 为了找到一个给定的内存地址属于哪一个内存区域。

find_vma_prev
 返回第一个小于addr的VMA

find_vma_intersection
 返回第一个和指定地址区间相交的VMA

15.5 mmap()和do_mmap():创建地址区间

do_mmap()

 内核使用do_mmap()函数创建一个新的线性地址区间。如果创建的地址区间和一个已经存在的地址区间相邻,并且有相同的权限的话,两个区间合并为一个。如果不能合并,要创建一个新的VMA。
 do_mmap()会将一个地址区间加入到进程的地址空间。

mmap()

 用户空间可以通过mmap()系统调用获得内核函数do_mmap()的功能。

15.6 mummap()和do_mummap()

do_mummap()从特定的进程地址空间中删除指定地址区间

15.7 页表

功能
 程序访问一个虚拟地址时,要将虚拟地址转化为物理地址,处理器才能解析地址访问请求。地址的转换工作需要通过查询页表才能完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值