【MIT 6.S081】2020, 实验记录(6),Lab: Copy-on-Write Fork

目录

    • Task: Implement copy-on write
      • step 1:对内存块进行引用计数
      • step 2:`uvmcopy` 实现 fork 时将 parent 的物理页映射到 child 中
      • step 3:在 `usertrap` 中增加对 page fault 的处理
      • 执行测试

官方说明:Lab: Copy-on-Write Fork for xv6

这个实验是利用 page fault 实现操作系统的 Copy-On-Write 功能(COW)。

COW 的意思是说,当 fork 时,子进程不会完全拷贝父进程的整个内存空间,而是与父进程共享同一份物理内存,并在 page table 中记录映射关系,当任意一个进程需要写某块内存时,会发生 page fault,page fault handler 会真正分配出一块新的内存并重新建立映射,从而节省了大量的内存拷贝。

通过这个 lab,对 COW 有了更深的了解。

Task: Implement copy-on write

这个 task 的要求是实现 COW,并通过 cowtestusertests

step 1:对内存块进行引用计数

由于多个进程可能会共享同一份物理内存,因此像 kfree() 这类函数不能随意释放一个物理内存,而是需要借助引用计数来决定能否真正释放物理内存,所以我们需要实现对每个物理内存块的引用计数。

kalloc.c 文件中,我们模仿 kmem 结构体写一个 kref,用来对每个内存块进行引用计数:

struct {struct spinlock lock;int counts[PHYSTOP / PGSIZE];
} kref;

kinit() 对 kref 进行初始化:

kinit

更改引用计数的函数:

// 增加对某个物理地址的引用计数
void
kref_inc(uint64 pa)
{acquire(&kref.lock);kref.counts[pa / PGSIZE]++;release(&kref.lock);
}// 减少对某个物理地址的引用计数
void
kref_dec(uint64 pa)
{acquire(&kref.lock);kref.counts[pa / PGSIZE]--;release(&kref.lock);
}// 获取某个物理地址的引用计数
int
kref_count(uint64 pa)
{int count;acquire(&kref.lock);count = kref.counts[pa / PGSIZE];release(&kref.lock);return count;
}

然后修改 kalloc(),当新分配一个物理内存块时,其引用计数应当为 1:

kalloc
然后是修改 kfree() 函数,当通过 kfree 想释放一个内存块时,需要检查这个内存块的引用计数,如果存在多个引用,只需要对引用计数 -1 即可,只有当没有更多进程引用这个内存块时,才能真正释放它:

kfree

step 2:uvmcopy 实现 fork 时将 parent 的物理页映射到 child 中

调用 fork 时,会使用 uvmcopy 来克隆一份 parent 的物理内存空间给 child,而我们为了实现 COW,在这里只需要共享同一个物理内存。

具体的做法就是,遍历 parent 的整个内存空间,将其物理地址封装成 PTE 放入 child 的 page table 中,同时需要将 parent 和 child 的 PTE 都改为只读的,这样之后任一进程在 write 时能够发生 page fault 并进而完成实际的内存分配。

除了 PTE 需要设置为只读的,还需要在 PTE 标记一下这是一个 COW page,从而与普通的只读 page 进行区分,为此,需要使用 PTE 中的预留位作为 COW 标志位:

PTE_COW
修改 uvmcopy

uvmcopy
这一块代码对原有拷贝整个内存空间的代码进行改造,实现遍历整个内存空间,并获取每块内存的 PTE 和物理地址,对 PTE 的 flags 做了修改后,再将其添加到 child 的 page table 中。另外注意,需要增加对物理内存的引用计数,因为这里每个内存增加了一个 child 进行对其的引用。

step 3:在 usertrap 中增加对 page fault 的处理

当一个被标为 COW 的只读 page 发生 page fault 时,我们需要对其进行 COW 的处理,为其分配一份新的物理内存,并修改 page table 中的映射,这样当 page fault 被处理并恢复正常流程后,就可以对内存进行 write 了。

首先我们需要一个函数来判断一个 page 是否为 COW page:

// 判断是否为 cow page
// 是的话返回 1,否则返回 0
int is_cowpage(pagetable_t pagetable, uint64 va){if (va >= MAXVA)return 0;pte_t *pte = walk(pagetable, va, 0);if(pte == 0)return 0;if ((*pte & PTE_V) == 0)return 0;return (*pte & PTE_COW) != 0;
}

另外我们将处理 COW 导致的 page fault 的逻辑封装为函数 handle_cow()

void* handle_cow(pagetable_t pagetable, uint64 va){va = PGROUNDDOWN(va);pte_t *pte = walk(pagetable, va, 0);if(pte == 0)return 0;uint64 pa = PTE2PA(*pte);if (pa == 0)return 0;// 根据 ref count 判断是否需要分配新的物理页if (kref_count(pa) == 1) {// 如果只存在一个引用,则直接修改 PTE 的 flags 并返回即可*pte |= PTE_W;  // 增加 PTE 的写权限*pte &= ~PTE_COW;  // 清除 PTE 的 COW 标志return (void*)pa;}// 如果存在多个引用,则需要分配新的物理页并拷贝旧页面内容char *mem = kalloc();  // 分配物理内存if (mem == 0) {return 0;}memmove(mem, (void*)pa, PGSIZE);  // 拷贝旧页面内容// 修改 va 的 mapping*pte = PA2PTE(mem) | ((PTE_FLAGS(*pte) | PTE_W) & (~PTE_COW));// 将旧物理页的 ref count 减一kfree((void*)pa);return mem;
}

这里的易错点:

  • 我们需要通过物理页的 ref count 来决定处理 COW page fault 时,是否需要分配一个新的物理页,因为当被标为 COW page 时,是两个及以上的进程来共享同一个物理 page,当随着有些进程因为 COW page fault 而创建了新的内存块而减少 ref count,直到当 ref count 为 1 时,发生 COW page fault 的进程就不再需要分配新的物理页,而是直接将之前的物理页恢复可写的 flag 即可。
  • 修改 PTE 的 flags 时,注意不要出错

有了这两个函数,我们就可以在 usertrap() 中增加对 page fault 的处理逻辑:

usertrap

在发生 page fault 时,会有三种可能:

  1. 访问了非法内存页
  2. 内存页合法,但是权限不合适(比如在不可执行的 page 上执行指令等)
  3. 在 COW 的只读 page 上执行 write 操作。这也是我们唯一能处理并恢复的 page fault

完成以上修改后,这个实验就完成了。

执行测试

make qemu 后分别执行 cowtestusertests

cowtest
测试通过~

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

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

相关文章

C++进阶-- map和set

关联式容器 在前面,我们所学的vector、list、deque,这些都是序列容器,也就是底层为线性序列的数据结构。 而关联式容器是C标准库中的一种类别,用于存储键值对(key-value pair),关联式容器中的元…

vxe-table编辑单元格动态插槽slot的使用

业务场景:表格中只有特定某一行的的单元格可以编辑,列很多,为每个列写个插槽要写很多重复代码,所以这里使用动态插槽,简化代码量。显示编辑图标,点击编辑图标隐藏。失去焦点保存调后台接口。 解决办法&…

十行代码开发一个AI应用

Semantic Kernal 简介 Semantic Kernel (SK) is a lightweight SDK that lets you easily mix conventional programming languages with the latest in Large Language Model (LLM) AI "prompts" with templating, chaining, and planning capabilities out-of-the-…

关于vue中关于eslint报错的问题

1 代码保存的时候会自动将单引号报错为双引号 导致eslint报错的问题, 解决思路: 在项目根目录下新建一个.prettierrc.json文件 { “tabWidth”: 2,“useTabs”: false,“singleQuote”: true,“semi”: false} 2 关于报错代码的时候 出现尾随逗号报错…

Zabbix 系统告警“More than 75% used in the configuration cache”处理办法

Zabbix系统报错提示 Zabbix 系统告警“More than 75% used in the configuration cache”,看了一下意思是可用的配置缓存超过75%。 修改缓存大小 vim /etc/zabbix/zabbix_server.confesc : /CacheSize 找到配置 将64M改大一点,保存退出。 重启zabbix…

【MySQL】数据库中常用的函数

目录 聚合函数COUNT()函数的多种用法COUNT(*)COUNT(主键)COUNT(1)COUNT(常量)COUNT(非主键)COUNT(distinct(字段)) COUNT()函数小结 字符函数length(str)函数:获取参数值的字节个数concat(str1,str2,...)函数:字符串拼接upper(str)、lower(str)函数:大小…

Linux高负载排查最佳实践

在Linux系统中,经常会因为负载过高导致各种性能问题。那么如何进行排查,其实是有迹可循,而且模式固定。 本次就来分享一下,CPU占用过高、磁盘IO占用过高的排查方法。 还是那句话,以最佳实践入手,真传一句话…

数据库-第二/三章 关系数据库和标准语言SQL【期末复习|考研复习】

前言 总结整理不易,希望大家点赞收藏。 给大家整理了一下计数据库系统概论中的重点概念,以供大家期末复习和考研复习的时候使用。 参考资料是王珊老师和萨师煊老师的数据库系统概论(第五版)。 文章目录 前言第二、三章 关系数据库和标准语言SQL2.1 关系2…

JVM原理-基础篇

Java虚拟机(JVM, Java Virtual Machine)是运行Java应用程序的核心组件,它是一个抽象化的计算机系统模型,为Java字节码提供运行环境。JVM的主要功能包括:类加载机制、内存管理、垃圾回收、指令解释与执行、异常处理与安…

虚拟机内存不够用了?全流程操作Look一下?

虚拟机信息:操作系统:CentOS Linux 7 (Core),用的是VMware Workstation 16 Pro 版本16.2.3 build-19376536;我的主机 Windows 10 Education, 64-bit (Build 22000.1817) 10.0.22000 前言:虚拟机用久了就会出现内存不足…

Rocky Linux 安装部署 Zabbix 6.4

一、Zabbix的简介 Zabbix是一种开源的企业级监控解决方案,用于实时监测服务器、网络设备和应用程序的性能和可用性。它提供了强大的数据收集、处理和可视化功能,同时支持事件触发、报警通知和自动化任务等功能。Zabbix易于安装和配置,支持跨平…

【前端素材】推荐优质后台管理系统网页Hyper平台模板(附源码)

一、需求分析 1、系统定义 后台管理系统是一种用于管理和控制网站、应用程序或系统的管理界面。它通常被设计用来让网站或应用程序的管理员或运营人员管理内容、用户、数据以及其他相关功能。后台管理系统是一种用于管理网站、应用程序或系统的工具,通常由管理员使…

【AIGC】OpenAI推出王炸级模型sora,颠覆AI视频行业(2024)

对于OpenAI推出的Sora模型,我们可以进一步探讨其可能的技术细节、潜在应用以及对AI视频行业的影响。 点击以下任一云产品链接,跳转后登录,自动享有所有云产品优惠权益: 经过笔者亲测,强烈推荐腾讯云轻量应用服务器作…

【分类讨论】【割点】1568. 使陆地分离的最少天数

作者推荐 动态规划的时间复杂度优化 本文涉及知识点 分类讨论 割点 LeetCode1568. 使陆地分离的最少天数 给你一个大小为 m x n ,由若干 0 和 1 组成的二维网格 grid ,其中 1 表示陆地, 0 表示水。岛屿 由水平方向或竖直方向上相邻的 1 …

接口详细说明

接口概述 接口也是一种规范 接口的定义与特点 接口的格式如下: //接口用关键字interface来定义 public interface 接口名 {// 常量// 抽象方法 } JDK8之前接口中只能是抽象方法和常量,没有其他成分了。 接口不能实例化。 接口中的成员都是public修…

svn介绍 4.0

一、svn介绍(版本控制工具) 1、svn的定义: svn是一个开放源代码的版本控制系统,通过采用分支管理系统的高效管理,简而言之就是用于多个人共同开发同一个项目,实现共享资源,实现最终集中式个管…

电脑数据丢失是什么原因 易我数据恢复软件下载 easyrecovery数据恢复软件下载 电脑数据删除了怎么恢复 电脑数据库损坏了怎么找回

目录 一、电脑数据丢失是什么原因 二、电脑数据丢失如何恢复 三、EasyRecovery恢复电脑数据的方法介绍 电脑是我们大家熟悉并且常用的数据存储设备,也是综合性非常强的数据处理设备。对于电脑设备来讲,最主要的数据存储介质是硬盘,电脑硬…

CMU15445实验总结(Spring 2023)

CMU15445实验总结(Spring 2023) 背景 菜鸟博主是2024届毕业生,学历背景太差,导致23年秋招无果,准备奋战春招。此前有读过LevelDB源码的经历,对数据库的了解也仅限于LevelDB。奔着”有对比才能学的深“的理念,以及缓解…

linux系统Jenkins工具配置webhook自动部署

Jenkins工具webhook自动部署 webhook自动部署webhook的意义操作流程jenkins页面操作gitlab页面操作 webhook自动部署 webhook的意义 自动化部署:Webhook 可以在代码提交、合并请求或其他特定事件发生时自动触发 Jenkins 构建和部署任务,从而实现自动化…

C#,K中心问题(K-centers Problem)的算法与源代码

1 K中心问题(K-centers Problem) k-centers problem: 寻找k个半径越小越好的center以覆盖所有的点。 比如:给定n个城市和每对城市之间的距离,选择k个城市放置仓库(或ATM或云服务器),以使城市…