《深入Linux内核架构》第4章 进程虚拟内存(2)

目录

4.3 内存映射原理

4.4 数据结构

4.4.1 树和链表

4.4.2 虚拟内存区域VMA的表示

4.4.3 相关数据结构


本节讲VMA结构体struct vm_area_struct和struct address_space。

4.3 内存映射原理

所有进程的虚拟空间总和比物理内存大得多,因此只有最常用的虚拟空间才映射到物理内存。

当访问一个未映射物理内存的虚拟内存时,进行按需调页。

按需调页步骤:

        进程访问用户空间虚拟地址,但无法通过页表找到对应物理地址。

        CPU触发缺页异常。

        通过虚拟地址对应address_space结构体,找到磁盘数据。

        分配物理内存页,读取磁盘数据到内存。

        建立正确页表,进程恢复执行。

后续详解。

4.4 数据结构

struct mm_struct:提供了进程在内存布局的所有必要信息。

struct mm_struct {

        ...

        struct vm_area_struct         *mmap;         链表,用于遍历该进程所有vma

        struct rb_root                       mm_rb;         红黑树,用于查找和插入该进程vma

        struct vma_area_struct        *mmap_cache;         缓存上一次find_vma结果

        ...

}

4.4.1 树和链表

每个区域(VMA)都用一个vm_area_struct表示,如代码段,数据段,堆,栈。

一个进程的所有VMA同时有两种排序方式:

        1. 单链表:mm_struct->mmap

                VMA根据起始地址以递增顺序放入mm_struct->mmap链表。

                作用:链表使用于遍历VMA。

        2. 红黑树:根节点为mm_struct->mm_rb

                VMA太多时,查找/插入操作等用红黑树更快。

4.4.2 虚拟内存区域VMA的表示

虚拟内存区域:即VMA。如:

        一个进程空间的代码段,数据段,堆,栈,mmap映射区域等。

每个VMA用struct vm_area_struct实例表示。

应用层哪些操作时会生成一个VMA:

        mmap函数。

        运行可执行文件或共享库。

        堆栈增长。

        shmat创建共享内存。

        malloc函数大内存。

两种映射:

        1. 匿名映射:没有对应映射的文件,如:

                堆,栈,mmap的MAP_ANONYMOUS类型映射。

                创建映射方法:

                        void *addr = mmap(NULL, size, PROT_READ|PROT_WRITE,                                 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); //fd为-1

        2. 文件映射:有对应映射源文件,如:

                数据段,代码段(对应可执行文件的.data和.text section)。

                创建映射方法:

                        void *addr = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, fd, 0);

struct vm_area_struct {

        struct mm_struct         *vm_mm;         

                所属mm_struct

       

         unsigned long              vm_start,vm_end;         

                该vma起始与结束地址

        

        struct vm_area_struct         *vm_next, *vm_prev;

                mm_struct中vma链表中前/后一个VMA(如上图)

      

          pgprot_t                 vm_page_prot;

        unsigned long         vm_flags;

        struct rb_node         vm_rb;

        union {

                struct {

                        struct rb_node rb;

                        unsigned long rb_subtree_last;

                } linear;

                struct list_head nonlinear;

        } shared;

        struct list_head           anon_vma_chain;

        struct anon_vma         *anon_vma;

        struct vm_operations_struct         *vm_ops;

        

        unsigned long         vm_pgoff;

                映射的文件位置的偏移量。

                若映射整个文件则为0。

        struct file         *vm_file;

                表示被映射的文件。

               若匿名映射,则为NULL。

}

成员解释:

1. pgprot_t vm_page_prot:

        该vma对应物理页的权限。值有:

                PROT_READ:允许读取页面。

                PROT_WRITE:允许写入页面。

                PROT_EXEC:允许执行页的代码。

                PROT_NONE:不允许任何访问。

        用法:entry = mk_pte(page, vma->vm_page_prot); //生成对应权限的页表项。

2. vm_flags:

        该VMA访问权限。值有:

                VM_READ,VM_WRITE,VM_EXEC:可读,可写,可执行

                VM_SHARD:该VMA由多进程共享。

                VM_PRIVATE:该VMA是私有的

                VM_MAYREAD:可设置为可读。

                VM_GROWSUP:该VMA向上扩展,如栈。

                VM_DONTCOPY:fork函数时不复制该VMA。

        根据VMA的访问权限(vm_flags)获取对应页面的保护权限(vm_page_prot)

                vma->vm_page_prot = vm_get_page_prot(vma->vm_flags) ;

3. struct vm_area_struct *vm_next, *vm_prev;

        mm_struct中struct vm_area_struct * mmap:是一个链表头。

                链表作用:连接了该进程的所有vma,便于遍历VMA。

        vm_prev:前一个VMA

        vm_next:后一个VMA

        注意:VMA地址递增排序。

4. struct rb_node vm_rb;

        mm_struct中struct rb_root mm_rb:一个红黑树根节点。

                mm_rb作用:

                        包含该进程的所有VMA到红黑树中,便于高效查询VMA。

        vm_rb:树节点,用于插入到红黑根节点中。

5. union {

        struct {

                struct rb_node rb;                 线性映射

                unsigned long rb_subtree_last;

        } linear;

        struct list_head nonlinear;         非线性映射

} shared;

用于文件映射的VMA:

1. VMA是线性映射

        struct rb_node rb作用:

                将该VMA插入到以address_space->i_mmap为根结点的红黑树。

2. VMA是非线性映射(即该VMA映射到多个非连续的物理内存区域。)

        struct list_head nonlinear作用:

                将该VMA连接到address_space->i_mmap_nonlinear链表中。

address_space作用:

        同一文件被映射到不同进程,有多个VMA。

        address_space通过红黑树或链表管理所有VMA。

        所以通过address_space,可知道一个文件被映射到哪些VMA。

线性映射:

        将虚拟地址简单偏移得到物理地址。如文件和共享库的映射。

非线性映射:

        被映射到多个非连续物理内存。如大文件映射。

6. struct list_head anon_vma_chain

        struct anon_vma *anon_vma

        (后续章节详解)

        刚创建子进程后,父子进程会共享相同地址空间,包括匿名页。

        管理共享同一匿名页的所有VMA。

匿名页时,stuct page->struct address_space *mapping不是指向struct address_space,而是struct anon_vma。

struct address_space管理文件映射的VMA,而struct anon_vma管理匿名映射的VMA。

如何找到映射该匿名页的所有VMA:

page -> struct anon_vma -> struct anon_vma_chain -> VMA

7. struct vm_operations_struct vm_ops:

        该VMA的操作函数。

        struct vm_operations_struct {

                void (*open)(struct vm_area_struct * area);

                void (*close)(struct vm_area_struct * area);

                        创建/删除vma,不常用,设为NULL。

                int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);

        };

fault函数使用场景:

        缺页异常:

                某虚拟地址没有分配对应物理页,触发缺页异常。

                执行fault函数,分配页,并读取数据到页中。

        写时复制COW:

                向只读映射写数据时,触发写时复制。

                执行fault函数,分配页作为副本并写入数据,不影响其他进程共享页面。

        共享页面拷贝:

                进程尝试写共享页时,fault将创建分配页,作为私有副本,并写入数据。

多进程共享同一物理页可节约内存。使用场景:

        执行相同程序:可共享代码段的页。

        动态库:共享库的代码段和数据段。基于写时复制,同一变量在不同进程的值不同。

        文件映射:映射同一文件到多进程,如映射数据库系统。

        共享内存IPC:多进程映射同一内存,进行进程间通信。

4.4.3 相关数据结构

struct file:内核中表示一个打开的文件。

struct file {

        struct inode                         *f_inode;             对应磁盘文件

        struct address_space         *f_mapping;         该文件映射信息

}

struct address_space {

        struct inode                         *host;         缓存的磁盘文件

        struct radix_tree_root         page_tree;

                该树连接了缓存了文件host的所有页page。

        作用:

                1. 通过该树,可查找到缓存文件指定偏移index的页。

                2. 可知某文件指定偏移处是否被缓存。若缓存,直接操作页,不用从磁盘读取。

                        //radix_tree_insert(&mapping->page_tree, index, page);

        struct rb_root                    i_mmap;

                红黑树,连接该文件的线性映射的所有VMA。

        struct list_head                 i_mmap_nonlinear;

                链表,连接该文件的非线性映射的所有VMA。

        struct address_space_operations         *a_ops;

}

address_space作用:

        1. 关联了文件和映射该文件的页(页缓存)。

                即关联struct inode *host和struct radix_tree_root page_tree。

        2. 保存映射该文件所有VMA。

                即struct rb_root i_mmap树和struct list_head i_mmap_nonlinear链表。

struct inode {         inode对应一个磁盘文件

        struct address_space         *i_mapping;

}

struct file {                 file对应一个已打开的文件

        struct inode                         *f_inode;

        struct address_space         *f_mapping;

}

打开文件时:

        file->f_mapping = inode->i_mapping;

一个进程多次打开同一个文件,内核为每次打开创建一个struct file实例。

而struct inode只有一个。

struct inode和struct file都包含struct address_space。

通过address_space的host成员可找到文件inode。

再通过inode中主/次设备号找到块设备文件。

如何将文件1.c的从头偏移100到1000区域映射到内存中?

        fd = open("/tmp/1.c", O_RDONLY);

        mmap(NULL, 900, PROT_READ, MAP_PRIVATE, fd, 100);

除了映射文件,mmap还可直接映射raw设备。
        作用:绕过文件系统接口和文件缓冲区。
        fd = open("/dev/mtdlbock1", O_RDONLY);
        mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, offset);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/302523.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

生活日常韩语成人外语培训中为什么韩国人说话喜欢用“~도록”?

많이 받는 질문 중 하나가 ‘~도록’을 자신에게 쓸 수 있는가 하는 것이다. 즉 “제가 하도록 하겠습니다” “조심하도록 하겠습니다” “말씀드리도록 하겠습니다” 등과 같은 표현이다. 我经常被问到的问题之一就是能否将“~도록”用于自己。比如“我来做吧”、“我会小心…

深度学习500问——Chapter06: 循环神经网络(RNN)(2)

文章目录 6.4 CNN和RNN的区别 6.5 RNNs与FNNs有什么区别 6.6 RNNs训练和传统ANN训练异同点 6.7 为什么RNN训练的时候Loss波动很大 6.8 标准RNN前向输出流程 6.9 BPTT算法推导 6.9 RNN中为什么会出现梯度消失 6.10 如何解决RNN中的梯度消失问题 6.4 CNN和RNN的区别 类别特点描述…

sfml sdl2 windows vscode 调试和coderunner插件运行

链接库写在编译链接命令里,如果没有使用到不会加入到生成的可执行文件里。所以tasks.json可以这样写, {"version": "2.0.0","tasks": [{"type": "cppbuild","label": "C/C: g.exe 生…

Apache Pulsar源码解析之Lookup机制

文章目录 引言Lookup是什么客户端实现原理服务端实现原理总结 引言 在学习Pulsar一段时间后,相信大家也或多或少听说Lookup这个词,今天就一起来深入剖析下Pulsar是怎么设计的它吧 Lookup是什么 在客户端跟服务端建立TCP连接前有些信息需要提前获取&am…

arm-linux-gnueabihf-gcc默认目录

默认编译的头文件目录: /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib 默认编译的库文件目录: /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/include/ …

vscode 重命名很慢或失败 vscode renames are slow

网上问题, 插件问题(我遇见的排除,不是)被其他程序占用问题,(我这边是这个) 解决方案: 打开【资源管理器】,使用火绒 或其他软件,查看文件夹 or 文件 被哪个…

2024.4.9-day12-CSS 常用样式属性和字体图标

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 作业 作业 <!DOCTYPE html> <html lang"zh-CN"><he…

go之web框架gin

介绍 Gin 是一个用 Go (Golang) 编写的 Web 框架。 它具有类似 martini 的 API&#xff0c;性能要好得多&#xff0c;多亏了 httprouter&#xff0c;速度提高了 40 倍。 如果您需要性能和良好的生产力&#xff0c;您一定会喜欢 Gin。 安装 go get -u github.com/gin-gonic/g…

【C++】unordered 系列关联式容器

文章目录 1. unordered 系列关联式容器2. unordered_map2.1 unordered_map 的文档介绍2.2 unordered_map 的接口说明 3. unordered_set4. 在线 OJ 1. unordered 系列关联式容器 在 C 98 中&#xff0c;STL 提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可…

STM32中C编程引入C++程序

C具备类的创建思想很实用于实际场景多相似性的框架搭建&#xff1b;同种类型或相似类型的C的优势明显因此进行相互嵌套使用 需要在C中使用C类的话&#xff0c;你可以通过C的“extern "C"”语法来实现。这允许你在C代码中使用C的链接方式&#xff0c;而在C代码中使用…

实现RAG:使用LangChain实现图检索查询

你是不是有时会遇到这样的问题&#xff1a;你可能遇到的任何主题或问题&#xff0c;都有大量的文档&#xff0c;但是当尝试将某些内容应用于自己的用途时&#xff0c;突然发现很难找到所需的内容。 在这篇博文中&#xff0c;我们将看一下LangChain是如何实现RAG的&#xff0c;这…

kali基础渗透学习,永恒之蓝,木马实战

简介 kali的学习本质是在linux上对一些攻击软件的使用&#xff0c;只是学习的初期 先在终端切换到root用户&#xff0c;以便于有些工具对权限的要求 下载链接 镜像源kali 攻击流程 公网信息搜集 寻找漏洞&#xff0c;突破口&#xff0c;以进入内网 进入内网&#xff0c…

码蹄集部分题目(第五弹;OJ赛2024年第10期)

&#x1f40b;&#x1f40b;&#x1f40b;竹鼠通讯&#xff08;钻石&#xff1b;分治思想&#xff1b;模板题&#xff1a;就算几何平面点对问题&#xff09; 时间限制&#xff1a;3秒 占用内存&#xff1a;128M &#x1f41f;题目描述 在真空中&#xff0c;一块无限平坦光滑…

秋招算法刷题6

20240408 1.两数之和 &#xff08;时间复杂度是O&#xff08;n的平方&#xff09;&#xff09; public int[] twoSum(int[] nums, int target){int nnums.length; for(int i0;i<n;i){ for(int j1;j<n;j){ if(nums[i][j]target){ …

libVLC 提取视频帧使用OpenGL渲染

在上一节中&#xff0c;我们讲解了如何使用QWidget渲染每一帧视频数据。 由于我们不停的生成的是QImage对象&#xff0c;因此对 CPU 负荷较高。其实在绘制这块我们可以使用 OpenGL去绘制&#xff0c;利用 GPU 减轻 CPU 计算负荷&#xff0c;本节讲解使用OpenGL来绘制每一帧视频…

harmonyOS安装ohpm

下载 下载地址 HUAWEI DevEco Studio和SDK下载和升级 | 华为开发者联盟 初始化 注意&#xff1a;初始化ohpm前&#xff0c;需先完成node.js环境变量配置 1.解压文件&#xff0c;进入commandline-tools-windows-2.0.0.2\command-line-tools\ohpm\bin 2.执行&#xff1a; init.ba…

安卓开机启动流程

目录 一、整体框架二、流程代码分析2.1 Boot ROM2.2 Boot Loader2.3 Kernel层Kernel代码部分 2.4 Init进程Init进程代码部分 2.5 zygote进程zygote代码部分 2.6 SystemServer进程SystemServer代码部分 2.7 启动Launcher与SystemUI 三、SystemServices3.1 引导服务3.2 核心服务3…

C++进阶之路---何为智能指针?

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、为什么需要智能指针&#xff1f; 下面我们先分析一下下面这段程序有没有什么内存方面的问题&#xff1f;提示一下&am…

什么是HW,企业如何进行HW保障?

文章目录 一、什么是HW二、HW行动具体采取了哪些攻防演练措施三、攻击方一般的攻击流程和方法四、企业HW保障方案1.建意识2.摸家底3.固城池4.配神器5.增值守 一、什么是HW 网络安全形势近年出现新变化&#xff0c;网络安全态势变得越来越复杂&#xff0c;黑客攻击入侵、勒索病…

【腾讯云 TDSQL-C Serverless 产品体验】饮水机式使用云数据库

云计算的发展从IaaS&#xff0c;PaaS&#xff0c;SaaS&#xff0c;到最新的BaaS&#xff0c;FasS&#xff0c;在这个趋势中serverless(去服务器化&#xff09; 计算资源发展Physical -> Virtualisation -> Cloud Compute -> Container -> Serverless。 一、背景介绍…