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

网站建设方案如何写沈阳网站seo排名

网站建设方案如何写,沈阳网站seo排名,杭州it培训机构推荐,网页制作专业搜题前言 本来往年这里还有个Lazy Allocation的#xff0c;今年不知道为啥直接给跳过去了。. 其他篇章 环境搭建 Lab1: Utilities Lab2: System calls Lab3: Page tables Lab4: Traps Lab5: Copy-on-Write Fork for xv6 参考链接 官网链接 xv6手册链接#xff0c;这个挺重要…前言 本来往年这里还有个Lazy Allocation的今年不知道为啥直接给跳过去了。. 其他篇章 环境搭建 Lab1: Utilities Lab2: System calls Lab3: Page tables Lab4: Traps Lab5: Copy-on-Write Fork for xv6 参考链接 官网链接 xv6手册链接这个挺重要的建议做lab之前最好读一读。 xv6手册中文版这是几位先辈们的辛勤奉献来的呀再习惯英文文档阅读我还是更喜欢中文一点开源无敌 个人代码仓库 官方文档 1. 简单分析 写时拷贝Copy On Write技术之前在15445也写过了这里再简单介绍一下。我们知道fork的过程有一条就是子进程会拷贝父进程的内存空间但是这个拷贝是有一定开销的尤其是在需要拷贝的东西多的时候更明显。但是这就引出了一个问题——我们真的需要去拷贝吗很显然从逻辑上来看只有父进程或子进程对内存空间有修改时这种拷贝才是有意义的否则只是徒增开销而已。依此便提出了COW思想——我们将拷贝的时机推迟到某个进程修改内存的时候这样就可以优化掉很多无必要的开销。 落实到实现策略上Lab文档为我们描述了一种方案——平时fork我们只需要为父子进程添加一个指向原始页面的指针即可这个页面将被标记为只读。这样当父进程或子进程尝试写入页面时就会触发page fault这应该算异常吧这个时候再由内核去重新分配内存空间为进程提供一个可写的页面处理结束至此我们就基本实现了这个COW。 不过这么写产生了一个问题即是内存释放本来我们页面的释放是随着进程释放同步进行的但是上面描述的策略中的进程不再持有真实的内存页面而仅仅是一个引用为了处理释放我们可以采用引用计数的方法——我们可以在内存页的元信息meta data中单独保存一个值用于计数当我们的进程释放时递减引用计数然后当计数为0时再调用内存的释放。 需要注意的是这个过程描述起来非常简单在xv6上的实现也不太困难但是在实际的大型内核中总会有各种各样的细节问题Lab提供了一个探讨COW存在的问题的链接可以参考一下。 根据上面的分析我们可以将这个Lab分为三个部分做 在fork时造成内存复制的假象处理page fault在写时真实复制内存使用引用计数管理内存释放 下面我们就来实现吧 2. 在fork时实现页面复用而非复制 根据我们之前lab的经验以及lab中的hintfork中执行页面复制的操作是在vm.c下的uvmcopy完成的 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);flags PTE_FLAGS(*pte);if((mem kalloc()) 0) // 没有空闲内存goto err;memmove(mem, (char*)pa, PGSIZE); // 拷贝内存if(mappages(new, i, PGSIZE, (uint64)mem, flags) ! 0){kfree(mem);goto err;}}return 0;err:uvmunmap(new, 0, i / PGSIZE, 1);return -1; }可以看到整体的流程是先分配一个mem然后将父进程的pa拷贝到mem中去然后把这个mem映射到子进程上因此我们可以直接把pa映射过去即可 int uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) {pte_t *pte;uint64 pa, i;uint flags;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);*pte ~PTE_W; // 取消写权限pa PTE2PA(*pte);flags PTE_FLAGS(*pte);if(mappages(new, i, PGSIZE, pa, flags) ! 0){goto err;}}return 0;err:uvmunmap(new, 0, i / PGSIZE, 1);return -1; }3. 处理page fault 触发page fault就会trap而trap我们知道是在trap.c下的usertrap完成而处理fault需要判断fault的类型这在xv6里面是一个选择结构通过r_scause()的值来判断在去年其实有一个Lazy Allocation的Lab的里面有告诉我们r_scause()值为13或15为页面错误其中13为读错误15为写错误因此此处我们只需要处理值为15时的情况 else if (r_scause() 15) {uint64 stval r_stval();if (is_cow_fault(p-pagetable, stval)) {if (handle_cow_fault(p-pagetable, stval) 0) {printf(usertrap(): alloc failed!\n); p-killed 1; // 当内存分配完直接kill}}else {goto unexpected;}}else { unexpected:printf(usertrap(): unexpected scause %p pid%d\n, r_scause(), p-pid);printf( sepc%p stval%p\n, r_sepc(), r_stval());setkilled(p);}框架有了我们怎么来判断一个fault是不是cow导致的呢我们可以在PTE中用一位标记一下 查看参考手册我们可以看到8-9位是保留位因此我们可以把第八位用于保存COW 并在uvmcopy处置位 *pte | PTE_C; // 设置写时复制标志 然后我们在vm.c实现上面两个函数 int is_cow_fault(pagetable_t pagetable, uint64 va) {if (va MAXVA)return 0;pte_t* pte walk(pagetable, PGROUNDDOWN(va), 0);return pte (*pte (PTE_V | PTE_U | PTE_C)); }int handle_cow_fault(pagetable_t pagetable, uint64 va) {va PGROUNDDOWN(va);pte_t* pte walk(pagetable, va, 0);if (!pte) {return -1;}uint64 pa PTE2PA(*pte);uint flags (PTE_FLAGS(*pte) ~PTE_C) | PTE_W; // 取消写时复制标志设置写权限char* mem kalloc();if (!mem) {return -1;}memmove(mem, (char*)pa, PGSIZE);uvmunmap(pagetable, va, 1, 1); // 取消映射if (mappages(pagetable, va, PGSIZE, (uint64)mem, flags) ! 0) {kfree(mem);return -1;}return 0; }并在defs.h创建声明 int is_cow_fault(pagetable_t pagetable, uint64 va); int handle_cow_fault(pagetable_t pagetable, uint64 va);4. 引用计数管理内存释放 首先思考一下我们的引用计数怎么实现hint提示我们可以利用一个数组直接映射对应页的引用计数于是我们在kalloc.c中 // 引用计数的锁和保存值 struct spinlock cow_ref_lock; int cow_cnt[(PHYSTOP - KERNBASE) / PGSIZE]; #define PA2IDX(pa) (((uint64)(pa) - KERNBASE) / PGSIZE)初始化锁 void kinit() {initlock(kmem.lock, kmem);initlock(cow_ref_lock, cow_ref_lock); // 初始化引用计数的锁freerange(end, (void*)PHYSTOP); }然后定义自增操作与自减操作 void inc_ref(void* pa) // 自增引用计数 {acquire(cow_ref_lock);cow_cnt[PA2IDX(pa)];release(cow_ref_lock); }void dec_ref(void* pa) // 自减引用计数 {acquire(cow_ref_lock);cow_cnt[PA2IDX(pa)]--;release(cow_ref_lock); }完善alloc与free void kfree(void *pa) {dec_ref(r);if (cow_cnt[PA2IDX(r)] 0) // 只有引用计数为1时才释放return;struct run *r;if(((uint64)pa % PGSIZE) ! 0 || (char*)pa end || (uint64)pa PHYSTOP)panic(kfree);// 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); }// Allocate one 4096-byte page of physical memory. // Returns a pointer that the kernel can use. // Returns 0 if the memory cannot be allocated. void * kalloc(void) {struct run *r;acquire(kmem.lock);r kmem.freelist;if(r)kmem.freelist r-next;release(kmem.lock);if(r){cow_cnt[PA2IDX(r)] 1; // 将引用计数置1memset((char*)r, 5, PGSIZE); // fill with junk}return (void*)r; }然后我们思考一下什么时候引用计数需要增加呢那应该是fork的时候因此我们需要暴露出inc_ref略然后在uvmcopy中调用它 int uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) {pte_t *pte;uint64 pa, i;uint flags;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);if (*pte PTE_W) // 对于本身可写的页才去取消写权限{*pte ~PTE_W; // 取消写权限*pte | PTE_C; // 设置写时复制标志}pa PTE2PA(*pte);flags PTE_FLAGS(*pte);if(mappages(new, i, PGSIZE, pa, flags) ! 0){goto err;}inc_ref((void*)pa);}return 0;err:uvmunmap(new, 0, i / PGSIZE, 1);return -1; }最后还有个问题就是对于不会触发trap的页操作这里没有涉及到根据提示我们可以找到vm.c下的copyout这个函数是通过软件访问页表我们就仿照trap里为它新增一段逻辑 int copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len) {uint64 n, va0, pa0;while(len 0){va0 PGROUNDDOWN(dstva);if (is_cow_fault(p-pagetable, stval)) {if (handle_cow_fault(p-pagetable, stval) 0) {printf(copyout(): alloc failed!\n);return -1;}}pa0 walkaddr(pagetable, va0);if(pa0 0)return -1;n PGSIZE - (dstva - va0);if(n len)n len;memmove((void *)(pa0 (dstva - va0)), src, n);len - n;src n;dstva va0 PGSIZE;}return 0; }5. 测试 最后运行make grade评分即可这里说一下我遇到过的错 终端刚开回车两下就出现 panic: uvmunmap: not aligned : 原因是va没有对齐在单独写的那两个函数里对vaa使用va PGROUNDDOWN(va);即可Test file测试过不了: 原因是copyout没有改改了就行
http://www.zqtcl.cn/news/649749/

相关文章:

  • 工作室网站需要备案吗wordpress群发工具
  • 官方网站娱乐游戏城自己做网站的好处
  • 查询建设规范的网站1元网站建设精品网站制作
  • 社交网站的优点和缺点个人网页制作软件
  • 做一家算命的网站有没有专门做淘宝客的网站
  • 网站站点管理在哪里建筑施工图设计
  • 众筹网站开发周期网页云原神
  • 哪些网站可以免费做h5东莞制作企业网站
  • 帝国cms 网站地址设置深圳住房和建设部网站
  • 专业网站建设价格最优网页游戏大全电脑版在线玩
  • 建设租车网站wordpress+js插件开发
  • 定制网站开发与模板商务酒店设计网站建设
  • php 网站部署后乱码wordpress禁止调用头部
  • 网站权重低营销型企业网站建站
  • 大港油田建设网站长春市网站优化公司
  • 嘉峪关市建设局建管科资质网站室内设计入门教程
  • 久久建筑网会员登陆中心百度的搜索引擎优化
  • 做网站好还是做程序员好wordpress new图标
  • 秀洲住房与建设局网站徐州建设工程招投标官方网站
  • 做公司网站要注意哪些问题做章的网站
  • 南京建设网站维护洛阳最新通告今天
  • 网站名称创意大全wordpress公开课插件
  • 淮安市城市建设档案馆网站可以做网页的软件
  • 网站空间服务器wordpress 排除置顶文章
  • 有域名后怎么做网站邯郸做移动网站的地方
  • 商标可以做网站吗网站开发的大学生应届简历
  • 长沙长沙网站建设公司saas系统架构
  • 成都销售型网站长春财经学院多大
  • 手机自己制作表白网站app项目网络计划图怎么画
  • 品牌网站如何做seo浏览器正能量网址