当前位置: 首页 > wzjs >正文

网站怎么会k如果网站没有做icp备案

网站怎么会k,如果网站没有做icp备案,济南网红隧道,郑州建设工程交易中心网站本篇是 MIT6.S081 操作系统课程 Lab6 的实验笔记,目标是完成 fork() 写时复制(Copy-on-Write)的功能,算是上一个懒分配实验的延伸。 未修改的 fork() 会复制父进程所有的内存到子进程,这个过程耗时且浪费内存&#xf…

本篇是 MIT6.S081 操作系统课程 Lab6 的实验笔记,目标是完成 fork() 写时复制(Copy-on-Write)的功能,算是上一个懒分配实验的延伸。

未修改的 fork() 会复制父进程所有的内存到子进程,这个过程耗时且浪费内存,写时复制的核心思想是:

  • fork 阶段,新创建的子进程页表,映射到父进程的物理地址,父子进程页表指向的物理地址是相同的
  • 同时,将共享的物理页面映射成 只读。
  • 只有当父子进程中的某一方尝试修改共享的页面时,触发页面错误,OS 才真正为子进程复制该页面。
  • Lab6 地址:https://pdos.csail.mit.edu/6.828/2020/labs/cow.html
  • 我的实验记录:https://github.com/yibaoshan/xv6-labs-2020/tree/cow

在开始实验之前,你需要:

  1. 观看 Lecture 8 课程录播视频:Interrupts(中断)
    • YouTube 原版:https://www.youtube.com/watch?v=zRnGNndcVEA
    • 哔哩哔哩中译版:https://www.bilibili.com/video/BV19k4y1C7kA?vd_source=6bce9c6d7d453b39efb8a96f5c8ebb7f&p=8
  2. 阅读 《xv6 book》 第五章: 中断和设备驱动
    • 英文原版:https://pdos.csail.mit.edu/6.828/2020/xv6/book-riscv-rev1.pdf
    • 中译版:https://xv6.dgs.zone/tranlate_books/book-riscv-rev1/c5/s0.html

Implement copy-on write(hard)

Your task is to implement copy-on-write fork in the xv6 kernel. You are done if your modified kernel executes both the cowtest and usertests programs successfully.

实现 copy-on-write fork 功能,并通过 cowtest 和 usertests 测试程序。

实验要求不能在上一节懒加载代码的基础上改,请切换到 cow 分支。

实现思路视频中讲得比较清楚:

  1. 延迟复制/释放,把一个物理页的复制(kalloc() then memmove())和释放(kfree())操作,改为记录这个物理页面被多少个进程引用
    • 创建新的物理页,引用数 +1
    • 复制一个物理页面,该物理页的引用数 +1
    • 进程释放一个物理页面,引用计数 -1,只有最后一个进程解除引用时,才可以真正的释放物理内存。
    • 执行写时复制,物理页的引用数也需要 -1
  2. 写时复制,本实验的核心功能,当一个进程尝试向一个共享页写入的时候,执行创建新物理页并复制。
    • 为 PTE 新增标识,用来标记这个物理页是写时复制的共享页面。
    • 触发页面错误,OS 才真正为子进程复制该页面。

1、延迟复制/释放

首先我们需要新增引用记数,用来记录每个物理页面被多少个进程引用,内存的申请释放都在 kalloc.c 文件

...
struct {struct spinlock lock;struct run *freelist;
} kmem;// 物理地址转 index
#define PA2IDX(p) (((uint64)(p)) / PGSIZE)struct {struct spinlock lock; // 保证并发安全int ref_arr[PHYSTOP / PGSIZE]; // 每个物理页面的引用次数
} page_ref; // 模仿 kmem 新建页面引用结构
...

新建 page_ref 结构体,里面有个数组用来存储物理页面的引用次数,还有个 lock 自旋锁,用来保证多 CPU 的并发安全。

void
kinit()
{initlock(&kmem.lock, "kmem");initlock(&page_ref.lock, "pageref"); // 初始化 page_ref.lockfreerange(end, (void*)PHYSTOP);
}

初始化 page_ref.lock

void *
kalloc(void)
{...if(r){memset((char*)r, 5, PGSIZE); // fill with junk// 如果是新分配的有效物理页,引用计数为 1page_ref.ref_arr[PA2IDX(r)] = 1;}return (void*)r;
}

如果是新分配的有效物理页,引用计数需要为 1。

kfree() 释放函数也需要修改,释放一个物理页面,引用计数 -1,只有最后一个进程解除引用,没有进程映射到该物理页了,才真正释放页面

void
kfree(void *pa)
{struct run *r;if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP)panic("kfree");acquire(&page_ref.lock);// 只有页面的引用计数为 0,没有进程映射到该物理页了,才真正释放页面if(--page_ref.ref_arr[PA2IDX(pa)] <= 0) {// Fill with junk to catch dangling refs.memset(pa, 1, PGSIZE);r = (struct run*)pa;acquire(&kmem.lock);r->next = kmem.freelist;kmem.freelist = r;release(&kmem.lock);}release(&page_ref.lock);
}

同时,还需要给外部提供增加引用次数和复制物理页的函数


// 如果有必要,克隆一页物理页
void *ktry_pgclone(void *pa) {acquire(&page_ref.lock);// 这个物理页本来就只有一个地方引用,直接返回if(page_ref.ref_arr[PA2IDX(pa)] <= 1) {release(&page_ref.lock);return pa;}// 申请一页物理页uint64 newpa = (uint64)kalloc();if(newpa == 0) {release(&page_ref.lock);return 0;}// 复制老物理页内容到新页memmove((void*)newpa, (void*)pa, PGSIZE);// 老物理页引用减一page_ref.ref_arr[PA2IDX(pa)]--;release(&page_ref.lock);return (void*)newpa;
}// 增加物理页面的引用次数
void kparef_inc(void *pa) {acquire(&page_ref.lock);page_ref.ref_arr[PA2IDX(pa)]++;release(&page_ref.lock);
}

把原先的 vm.c 里面的 copy 工作,改为对这个物理页的引用次数 +1

int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
{pte_t *pte;uint64 pa, i;uint flags;
//  char *mem; // 不需要新的内存空间的for(i = 0; i < sz; i += PGSIZE){if((pte = walk(old, i, 0)) == 0)panic("uvmcopy: pte should exist");if((*pte & PTE_V) == 0)panic("uvmcopy: page not present");pa = PTE2PA(*pte);// 如果页面是可写权限,那把它标记为 COW 并移除写权限if (*pte & PTE_W) {*pte = (*pte & ~PTE_W) | PTE_COW;}flags = PTE_FLAGS(*pte);// 这里取消申请内存并复制的操作
//    if((mem = kalloc()) == 0)
//      goto err;
//    memmove(mem, (char*)pa, PGSIZE);// 将爸爸的物理地址映射到新的页表if(mappages(new, i, PGSIZE, (uint64)pa, flags) != 0){goto err;}// 将物理页的引用次数增加 1kparef_inc((void*)pa);}return 0;err:uvmunmap(new, 0, i / PGSIZE, 1);return -1;
}

2、写时复制

内存复制延迟到写操作,那就需要一种方来标记,哪些页面是写时复制的共享页面,我们这里用的是 PTE 的保留位来实现

kernel/riscv.h
...
#define PTE_U (1L << 4) // 1 -> user can access
#define PTE_COW (1L << 8)  // 第8位保留位用于标记 COW 页面

提供个方法,针对 cow 页面,执行创建新物理页并复制。

kernel/vm.c
// 处理 COW 页错误
int cow_handler(pagetable_t pagetable, uint64 va)
{pte_t *pte;// 拿到 va 对应的页表项if((pte = walk(pagetable, va, 0)) == 0)panic("uvmcowcopy: walk");uint64 pa = PTE2PA(*pte);uint64 newpa;// 转为 pa 丢到 kalloc 里面处理,因为涉及到物理页的记数操作if((newpa = (uint64)ktry_pgclone((void*)pa)) != 0){// 重新修改为可写,并删除 cow 标识uint64 flags = (PTE_FLAGS(*pte) | PTE_W) & ~PTE_COW;// 解除原来的映射,注意最后一个参数要传0,不释放物理页uvmunmap(pagetable, PGROUNDDOWN(va), 1, 0);// 映射到新的物理页if(mappages(pagetable, va, 1, newpa, flags) == -1) {panic("uvmcowcopy: mappages");}return 0;}return -1;
}

然后,如果发现是 cow 页面,就调用 cow_handler() 来处理。

kernel/vm.c
#include "spinlock.h"
#include "proc.h"
int
copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
{uint64 n, va0, pa0;pte_t *pte;struct proc *p = myproc();while(len > 0){va0 = PGROUNDDOWN(dstva);// 如果是 cow 页,执行复制if(va0 < p->sz && (pte = walk(pagetable, va0, 0))!=0 && *pte & PTE_V&& *pte & PTE_COW)cow_handler(pagetable,va0);pa0 = walkaddr(pagetable, va0);...
}
kernel/trap.c
void
usertrap(void) {...if (r_scause() == 8) {// system call...} else if ((which_dev = devintr()) != 0) {// ok} else if (r_scause() == 13 || r_scause() == 15) { // 和上一节实验一样,响应页错误pte_t *pte;uint64 va = r_stval();// 检查地址是否合法if (va >= p->sz)exit(-1);pte = walk(p->pagetable, va, 0);// 检查 pte 是否有效且是个 cow 页,不满足条件直接干掉进程if (pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_COW) == 0)exit(-1);// 如果是 cow 页面,尝试为它完成写时复制if (cow_handler(p->pagetable, va) == -1) {exit(-1);}} else {printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);printf("            sepc=%p stval=%p\n", r_sepc(), r_stval());p->killed = 1;}...
}

最后来执行测试用例 cowtest
在这里插入图片描述

测试通过,完整代码在:https://github.com/yibaoshan/xv6-labs-2020/commit/63b00eaae1c503792142d0e770fc99faaec6a182

参考资料

  • CS自学指南:https://csdiy.wiki/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/MIT6.S081/
  • Wings:https://blog.wingszeng.top/series/learning-mit-6-s081/
  • Miigon:https://blog.miigon.net/categories/mit6-s081/
  • 知乎专栏《28天速通MIT 6.S081操作系统》:https://zhuanlan.zhihu.com/p/632281381

文章转载自:

http://QfyvfVvB.rckLc.cn
http://4ehGY4qZ.rckLc.cn
http://oQKRI07N.rckLc.cn
http://W8LhC4WV.rckLc.cn
http://f3MjsDyE.rckLc.cn
http://S5jmXoBu.rckLc.cn
http://mqNhSc1S.rckLc.cn
http://ZT35PyL0.rckLc.cn
http://6ks8ubLz.rckLc.cn
http://IkUt2bFx.rckLc.cn
http://GOwYSsG8.rckLc.cn
http://pxvBsQ2e.rckLc.cn
http://lVKagXja.rckLc.cn
http://LGM9LpXz.rckLc.cn
http://BuXAuvCR.rckLc.cn
http://f1NpHC55.rckLc.cn
http://Kxy0tZ0Z.rckLc.cn
http://Xg1Xfhq8.rckLc.cn
http://LvL2ODoF.rckLc.cn
http://Lu18UwQm.rckLc.cn
http://HvnVyRET.rckLc.cn
http://nEO66zqY.rckLc.cn
http://FUFfccI3.rckLc.cn
http://IUoSNvUS.rckLc.cn
http://EymmXLOL.rckLc.cn
http://2IQqrZVU.rckLc.cn
http://Pkek5EP6.rckLc.cn
http://P1XXYlxo.rckLc.cn
http://7PJInYCy.rckLc.cn
http://Od7uf9mn.rckLc.cn
http://www.dtcms.com/wzjs/703846.html

相关文章:

  • 网站如何防止重登录设计师服务平台网
  • 营销型网站建设区别王也高清头像
  • 咨询类网站建设网页制作标题设置步骤
  • 网站开发后怎么上线如何自己设计创建一个网站
  • 网站如何做质保系统广点通广告平台
  • 做网站需要的软件前几年做那个网站能致富
  • 长春搜索引擎网站推广黄冈论坛遗爱网
  • 北京 网站建设 公东莞网站建设的公司
  • 营销型网站建设要点o2o网站建设效果
  • 长春网站建设方案托管做网站的外包公司上班好不好
  • 南京网站建设学习做网站网站是什么案件
  • 深圳网站建设找哪家公司wordpress的站点地址和
  • 网站上面怎么做链接做网站用python还是php
  • 企业形象网站开发seo排名优化排行
  • 网站老提示有风险最正规的购物平台
  • 做视频有赚钱的网站有哪些自然资源网站建设方案
  • 电商网站建设实训报告石排做网站
  • 3g医院网站模板湖南软件开发公司
  • 安全生产标准化建设网站商城网站建设企业
  • 保险行业网站建设做得好的网站建设公司
  • 做瞹瞹瞹视频网站php网站做代理服务器
  • 动画网站源码国外好用的免费服务器
  • wordpress 主题 支付宝seo效果检测步骤
  • 网站收录查询网2023最好用的浏览器
  • 大学网站建设策划书厦门市保障性住房官网
  • 做网站公司平台星宿网站建设
  • 青岛网站建设订做信息流广告公司
  • 朋友找做网站都要收定金个人开店的电商平台
  • 工程建设指挥部网站大连工商网站查询企业信息
  • 柳州商城网站开发单页网站如何做