Linux内核学习(十一)—— 进程地址空间(基于Linux 2.6内核)

目录

一、地址空间

二、内存描述符

三、虚拟内存区域

四、操作内存区域

find_vma()

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

五、页表


一、地址空间

进程地址空间由进程可寻址并且允许进程使用的虚拟内存组成, 每个进程都有一个 32 位或 64 位的平坦(flat)地址空间,空间的具体大小取决于体系结构。术语 “平坦(flat)” 指的是地址空间范围是一个独立的连续空间。每个进程都有唯一的这种平坦地址空间,一个进程的地址空间与另一个进程的地址空间即使有相同的内存地址,实际上也彼此互不相干。相对地,能与其他进程共享它们的地址空间的进程,被称为线程。

进程只能访问有效内存区域内的内存地址,每个内存区域也具有相关权限,如果一个进程访问了不在有效范围中的内存区域,或以不正确的方式访问了有效地址,那么内核就会终止该进程,并返回 “段错误(Segmentation Fault)” 信息

内存区域可以有如下类型的内容:

  • 代码段(text section),可执行文件代码的内存映射。
  • 数据段(data section),可执行文件的已初始化全局变量的内存映射。
  • bss 段(bss section),可执行文件的未初始化全局变量的内存映射。
  • 进程用户空间栈。
  • 内存映射文件。
  • 共享内存段。
  • 匿名的内存映射,比如由 malloc() 分配的内存。

二、内存描述符

内核使用内存描述符结构体表示进程的地址空间,该结构包含了和进程地址空间有关的全部信息。内存描述符由 mm_struct 结构体表示,定义在 <linux/sched.h> 中:

 

mm_users 域记录正在使用该地址的进程数目。比如,两个线程共享该地址空间,那么 mm_users 的值便等于 2;

mmap 和 mm_rb 这两个不同数据结构体描述的对象是相同的:该地址空间中的全部内存区域。但是前者以链表形式存放而后者以红黑树形式存放。mmap 结构体作为链表,利于简单、高效地遍历所有元素;而 mm_rb 作为红黑树,更适合搜索指定元素。

在进程描述符 task_struct 中的 mm 域就存放着该进程使用的内存描述符。fork() 函数利用 copy_mm() 函数复制父进程的内存描述符给子进程。通常,每个进程都有唯一的 mm_struct 结构体,即唯一的进程地址空间。

当进程退出时,内核会调用 exit_mm() 函数,内存描述符中的 mm_users 用户计数会减一,如果用户计数等于 0,则减少 mm_count 使用计数,如果该计数也为 0,则释放该结构体。

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

三、虚拟内存区域

虚拟内存区域(virtual memoryAreas,VMAs),由 vm_area_struct 结构体描述,定义在 <linux/mm_types.h> 中。该结构体描述了指定地址空间内连续区间上的一个独立内存范围。

vm_start 是内存区间的开始地址,而 vm_end 是内存区间的结束地址。

VMA 标志是一种位标志,定义于 <linux/mm.h>。包含在 vm_flags 域内,标志了内存区域所包含的页面的行为和信息。

vm_area_struct 结构体中的 vm_ops 域指向与指定内存区域相关的操作函数表,内核使用表中的方法操作 VMA。操作函数表由 vm_operations_struct 结构体表示,定义在文件 <linux/mm.h> 中:

四、操作内存区域

find_vma()

find_vma() 函数能识别给定的内存地址属于哪一个内存区域,定义在 <mm/mmap.c> 中:

struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr);

该函数在指定的地址空间中搜索第一个 vm_end 大于 addr 的内存区域。如果没找到这种区域,则函数返回 NULL,否则返回指向匹配的内存区域的 vm_area_struct 结构体指针。 

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

内核使用 do_mmap() 函数创建一个新的线性地址区间。

unsigned long do_mmap(struct file *file, unsigned long addr,
                      unsigned long len, unsigned long prot,
                      unsigned long flag, unsigned long offset)

该函数映射由 file 指定的文件,具体映射的是文件中从偏移 offset 处开始,长度为 len 字节的范围内的数据。如果 file 参数是 NULL 并且 offset 参数也是 0,那么就代表这次映射没有和文件相关,被称为匿名映射(anonymous mapping)。如果指定了文件名和偏移量,那么该映射就被称为文件映射(file-backed mapping)。 

在用户空间可以通过 mmap() 系统调用获取内核函数 do_mmap() 的功能。定义如下:

void *mmap2(void start, size_t length, int prot, int flags, int fd, off_t pgoff)

该系统调用是 mmap() 调用的第二种变种,最原始的 mmap() 调用中最后一个参数是字节偏移量,而 mmap2() 使用页面偏移作为最后一个参数。使用页面偏移量可以映射更大的文件和更大的偏移位置。

五、页表

虽然应用程序操作的对象是映射到物理内存之上的虚拟内存,但是处理器直接操作的却是物理内存。所以当应用程序访问一个虚拟地址时,首先必须将虚拟地址转化成物理地址,然后处理器才能解析地址访问请求。地址的转换工作需要通过查询页表才能完成,地址转换需要将虚拟地址分段,使每段虚拟地址都作为一个索引指向页表,而页表项则指向下一级别的页表或者指向最终的物理页面。 

Linux 中使用三级页表完成地址转换。利用多级页表能够节约地址转换需要占用的存放空间。

  • 顶级页表是页全局目录(PGD),PGD中的表项指向二级页目录中的表项:PMD。
  • 二级页表是中间页目录(PMD),其中表项指向 PTE 中的表项。
  • 最后一级简称页表,该页表直接指向物理页面。

多数体系结构中,搜索页表的工作是由硬件完成的。

 

为了加快查询速度,多数体系结构实现了一种高速缓存(translate lookaside buffer,TLB)。TLB 作为一个将虚拟地址直接映射到物理地址的硬件缓存,当请求访问一个虚拟地址时,处理器会首先检查 TLB 中是否缓存了该虚拟地址到物理地址的映射,如果在缓存中则直接命中,立即返回物理地址;否则,就要再通过页表搜索需要的物理地址。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Go】Goland项目配置运行教程

Golang项目配置运行教程 1.安装Golang下载安装包安装 2.Goland配置2.1 环境2.2 goland配置2.2.1 没有makefile的情况2.2.2 有makefile的情况 3.跨平台项目4.补充 注意&#xff0c;本项目描述的是git clone下来的Golang项目配置运行教程&#xff0c;并不是从头创建一个Golang项目…

大语言模型初学者指南 (2023)

大语言模型 (LLM) 是深度学习的一个子集&#xff0c;它正在彻底改变自然语言处理领域。它们是功能强大的通用语言模型&#xff0c;可以针对大量数据进行预训练&#xff0c;然后针对特定任务进行微调。这使得LLM能够拥有大量的一般数据。如果一个人想将LLM用于特定目的&#xff…

组件库的使用和自定义组件

目录 一、组件库介绍 1、什么是组件 2、组件库介绍 3、arco.design 二、组件库的使用 1、快速上手 2、主题定制 3、暗黑模式 4、语言国际化 5、业务常见问题 三、自定义组件 2、组件开发规范 3、示例实践guide-tip 4、业务组件快速托管 一、组件库介绍 1、什么是…

k8s 查看加入主节点命令 k8s重新查看加入节点命令 k8s输入删除,重新查看加入命令 kuberadm查看加入节点命令

1. 使用kuberadm 安装成功后&#xff0c;clear清除了屏幕数据&#xff0c;加入命令无法查看&#xff0c;使用如下&#xff0c;重新查看node如何加入主节点命令&#xff1a; kubeadm token create --print-join-command --ttl 0 2.画圈的全部是&#xff0c;都复制&#xff0c;在…

在Windows操作系统上安装Neo4j数据库

在Windows操作系统上安装Neo4j数据库 一、在Windows操作系统上安装Neo4j数据库 一、在Windows操作系统上安装Neo4j数据库 点击 MySQL可跳转至MySQL的官方下载地址。 在VUE3项目的工程目录中&#xff0c;通过以下命令可生成node_modules文件夹。 npm install&#xff08;1&am…

c语言练习题34:打印整数二进制的奇数位和偶数位

打印整数二进制的奇数位和偶数位 获取一个整数二进制序列中所有的偶数位和奇数位&#xff0c;分别打印出二进制序列 思路&#xff1a; 1. 提取所有的奇数位&#xff0c;如果该位是1&#xff0c;输出1&#xff0c;是0则输出0 2. 以同样的方式提取偶数位置检测num中某一位是0还…

Win 11 电脑的 Win + E 快捷键失效

报的错误信息如下&#xff1a; 该文件没有与之关联的应用来执行该操作。请安装应用&#xff0c;若已经安装应用&#xff0c;请在”默认应用设置"页面中创建关联。 报错原因&#xff1a;系统注册表被改写了导致的出错 解决办法&#xff1a; 1、首先&#xff0c;按键盘上…

js的使用之时间如何定义,窗口加载事件

1.时间如何定义 1.1 date的其他的属性 带出星期几的写法 var arr [星期日,星期一,星期二,星期三,星期四,星期五,星期六,星期天] var day date.getDay(); console.log(arr[day]); 1.2 日期的格式化 1.3 时分秒的写法 固定写法&#xff1a;如果想要写成00:00:00这种形式&am…

JVM第三篇 运行时数据区-虚拟机栈和PC程序计数器

目录 1. JAVA中的线程 2. 栈区 2.1 栈帧 2.2 栈可能出现的异常 2.3 设置栈大小 3.程序计数器&#xff08;PC&#xff09; 4. PC和栈发挥的作用 5. 关于栈的常见面试题 虚拟机包含三大部分&#xff0c;类加载子系统&#xff0c;运行时数据区&#xff0c;执行引擎。运行时…

数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成

数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成 目录 数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成生成效果基本描述程序设计参考资料 生成效果 基本描述 数据生成 | MATLAB实现GAN生成对抗网络结合SVM支持向量机的数据生成。 生成对抗…

Git工作流

实际开发项目使用到的分支: main&#xff1a;生产环境&#xff0c;也就是你们在网上可以下载到的版本&#xff0c;是经过了很多轮测试得到的稳定版本。 release&#xff1a; 开发内部发版&#xff0c;也就是测试环境。 dev&#xff1a;所有的feature都要从dev上checkout。 fea…

win11下MySQL8详细安装教程

文章目录 新建配置文件 my.ini初始化数据库安装服务启动服务 新建配置文件 my.ini 初始化数据库 mysqld --initialize --console记下初始密码 安装服务 mysqld --install启动服务 net start mysql修改密码请看另外文章 windows修改MySQL密码

汽车制造业外发文件时 如何阻断泄密风险?

汽车制造业是我国国民经济发展的支柱产业之一&#xff0c;具有产业链长、关联度高、就业面广、消费拉动大等特性。汽车制造行业景气度与宏观经济、居民收入水平和固定资产投资密切相关。 汽车制造业产业链长&#xff0c;关联度高&#xff0c;汽车制造上游行业主要为钢铁、化工…

C#,《小白学程序》第三课:类、类数组与排序

1 文本格式 /// <summary> /// 同学信息类 /// </summary> public class Classmate { /// <summary> /// 学号 /// </summary> public int Id; /// <summary> /// 姓名 /// </summary> public string Nam…

Unity 之 transform.rotate() 实现旋转

文章目录 详细介绍默认情况下&#xff0c;以局部坐标 详细介绍 在Unity中&#xff0c;Transform.Rotate() 是一个用于在物体上进行旋转的函数。它可以用来在局部坐标系下对物体进行旋转&#xff0c;也可以在世界坐标系下进行旋转。下面是关于 Transform.Rotate() 的详细介绍&a…

如何使用HTML5新增的标签来构建语义化的页面结构?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ <header>&#xff1a;⭐ <nav>&#xff1a;⭐ <main>&#xff1a;⭐ <section>&#xff1a;⭐ <article>&#xff1a;⭐ <aside>&#xff1a;⭐ <footer>&#xff1a;⭐ <figure> 和 &l…

【MongoDB系列】-MongoDB详解(一文让你明白什么是MongoDB)

MongoDB简介 MongoDB 是一个开源的、跨平台的、面向文档的、基于分布式文件存储的数据库系统&#xff0c;MongoDB 是由 C 语言开发&#xff0c;旨在为 Web 应用提供可扩展的高性能数据存储解决方案。在高负载的情况下&#xff0c;通过添加更多的节点&#xff0c;可以保证服务器…

【面试题】UDP和TCP有啥区别?

UDP UDP协议全称是用户数据报协议&#xff0c;在网络中它与TCP协议一样用于处理数据包&#xff0c;是一种无连接的协议。在OSI模型中&#xff0c;在第四层——传输层&#xff0c;处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点&#xff0c;也就…

【Git】测试持续集成——Git+Gitee+PyCharm

文章目录 概述一、使用Gitee1. 注册账号2. 绑定邮箱3. 新建仓库4. 查看项目地址 二、安装配置Git1. 下载安装包2. 校验是否安装成功。3. 配置Git4. Git命令5. Git实操 三、PyCharmGit1. 配置Git2. Clone项目3. 提交文件到服务器4. 从服务器拉取文件 概述 持续集成&#xff08;…

Elasticsearch 8.X reindex 源码剖析及提速指南

1、reindex 源码在线地址 为方便大家验证&#xff0c;这里给出 reindex github 源码地址。 https://github.com/elastic/elasticsearch/blob/001fcfb931454d760dbccff9f4d1b8d113f8708c/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java reindex 常见…