Linux kernel之二内存管理之进程虚拟地址空间

1.背景

虚拟内存的一大优势就是每个进程有自己的虚拟地址空间,OS 负责将其虚拟地址空间映射到物理内存中。
内核处理用户部分的地址空间的方式,与内核部分不同:

  • 内核部分内存的分配是立刻满足的,并对全局可见:
    1)__get_free_pages()或alloc_pages() 从page frame 分配器获取page frame;
    2)kmem_cache_alloc() 或kmalloc() 使用专用或通用的slab 分配器分配objects;
    3)vmalloc() 获取非连续的内存。
    如此简单的分配方式的两个原因是:
    1)内核是整个OS中优先级最高的部分;
    2)内核可靠安全,所有内核函数都是无error的,不需要加入保护以防止错误
  • 用户进程情况,则不同
    1)进程内存申请的请求,通常内核会推迟分配内存给用户进程;
    i. 每个进程通常实际使用的地址空间,就只有整个虚拟地址空间的其中的几个区域;并且每个区域相隔比较远。 内核需要高效管理这些分散的区域。
    ii. 进程可执行文件加载时,进程不可能在不远的将来会访问所有的code page;
    iii. 进程通过malloc()分配内存时,并不意味着进程会很快访问所有分配的内存
    2)用户进程并不可靠,内核必须捕捉所有用户态的错误以确保用户进程会破坏系统稳定性和安全性。

2. 进程虚拟地址空间

2.1 进程虚拟地址空间布局

(1)进程虚拟地址空间由很多虚拟内存区域(VMA)构成:

  • stack
    用于存放局部变量,函数参数和函数调用
  • mmap
    主要用于映射文件内容到虚拟地址空间的内存映射,也用于映射共享object 和动态库
  • heap
    动态分配的内存存放的地方,允许进程存放运行时的数据。malloc()分配的内存来自此区域
  • BSS
    存放未初始化的静态变量
  • data
    存放全局变量,静态初始化的变量
  • text
    映射程序二进制文件到内存的区域
    image.png

(2)每个VMA, 物理上映射到一到多个内存块,进程的page table 做相应的地址映射。

2.2 进程地址空间描述符

  • 进程可用的地址空间通过进程task_struct 中的struct mm_struct 结构管理
  • 每个进程有一个mm_struct ,用户线程共享同一个地址空间;
  • 通过寻找所有task_structs 中指向相同的mm_struct 可以识别出task list 中的线程;
  • 内核线程不需要mm_struct,通常内核线程的task_struct->mm为NULL;
image.png
  • mmap
    是进程地址空间中所有VMA 区域的链表头
  • mmap_cache
    缓存上次访问的VMA;
  • mm_rb
    所有的VMA 排放在链表mm_struct->mmap中,并为了快速查询,也放在红黑树中,这个是树的root
image.png
  • start_code, end_code
    对应程序二进制文件映射的code VMA 区域的起始和结束虚拟地址
  • start_data, end_data
    对应data VMA 区域的起始和结束虚拟地址
  • start_brk, brk
    对应heap VMA 区域的起始和当前结束的虚拟地址
  • start_stack
    对应stack VMA 区域的起始和当前结束的虚拟地址
  • arg_start, arg_end
    对应命令行参数列表的 VMA 区域的起始和当前结束的虚拟地址
  • env_start, env_end
    对应环境参数的 VMA 区域的起始和当前结束的虚拟地址


    image.png

2.3 虚拟内存区域VMA

  • 每个虚拟内存区域由vm_area_struct 管理


    image.png
  • VMA 区域之间不会重叠,每个VMA区域代表着相同保护访问方式和目的的的区域
  • 进程的完整的VMA区域可通过/proc/PID/maps 查看
  • vm_start, vm_end
    对应这个该vma 区域的起始虚拟地址和结束地址
  • vm_next
    VMA直接通过vm_next 链接到一起,通过地址排序
  • vm_rb
    VMA 通过vm_rb 链接到红黑树中
  • vm_mm
    指向所属的进程的mm_struct 结构
  • vm_file
    对于基于文件的VMA 区域(code 区,共享库,共享内存映射区等等),vm_file 指向对应文件的struct file 指针,该文件struct file ->f_dentry->d_inode->i_mapping 的struct address_space 拥有所有关于文件的信息,包含指向文件系统操作的文件系统函数
  • anon_vma_node
    heap,stack 和mmap 的虚拟地址空间的分配都通过匿名内存映射分配的, 内核通过struct anon_vma 将代表匿名内存的VMA区域链接到一起,便于快速访问所有的映射匿名页的进程VMA
  • vm_ops
    VMA 操作指针,open 和close 通常为NULL,nopage 用于page fault


    image.png
  • vm_operations_struct


    image.png

2.4 基于文件的VMA区域

  • 基于文件的VMA 区域 通过struct address_space 描述


    image.png
  • 每个address_space结构作为一个文件inode 对应的pages 的抽象
    i. 文件打开的时候,kernel 设置file->f_mapping为inode->i_mapping
    ii. inode 是per-file 数据结构,而file 是per-process 数据结构;这样让多个进程能直接访问同样的文件,而不需要与其他进程交互


    image.png
image.png
  • host
    指向拥有对于pages的owner inode;

  • i_mmap
    为了高效管理cache 中的文件pages, 需要跟踪所有映射到同一个address_space的VMA。 i_mmap 是所有包含当前映射到该address_space的VMA的红黑树。

  • page_tree
    i. 处于address_space对象的所有包含文件数据的物理page 都通过radix tree 数据结构组织管理起来以高效访问,page_tree 是radix tree 的root,是struct radix_tree_root 类型的实例;
    ii. 一方面一个进程的所有VMA 被同时组织管理在一个链表和红黑树数据结构中
    iii. 另一方面radix 树数据结构用于反向查找一个给定文件的所有VMA;


    image.png

    image.png

    image.png
  • struct radix_tree_root
    radix tree 的每个node 是struct radix_tree_node 类型的,struct radix_tree_root 中的*rnode 作为radix tree的 第一个node;


    image.png

    image.png

2.6 文件的虚拟地址空间与文件系统之间的联系

  • 文件的内存映射是两个不同地址空间的映射
    i. 一个地址空间是用户进程的虚拟内存地址空间;
    ii. 另一个是文件系统覆盖的地址空间;

  • 内核以read, write 请求的方式建立两个地址空间的联系

  • vm_operations_struct 结构体用于建立联系,提供方法读内容到物理内容


    image.png
  • 而具体的文件系统的操作是通过address_space 结构的address_space_operation
    i. readpage,readpages 读块设备的单个和多个页内容到内存中;
    ii.writepage,writepages 写内存中的单个页和多个页到块设备中对应的位置
    iii. set_page_dirty 标记页内容改变,不在与块设备中的内容一致


    image.png
  • vm_operation_struct 与 address_space 之间的联系
    i. 通过kernel 的标准实现vm_operations_struct 实例,几乎所有文件系统在使用 generic_file_vm_ops.

  • filemap_faul的实现使用底层文件系统对应的address_space提供的readpage 操作


    image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容